Here's a good way to define the format (combining a few concepts from ScalaJsonCombinators):
val personFormat: Format[PersonWithHobby] = (
(__ \ "id").format[String] and
(__ \ "name").format[String] and
(
(__ \ "hobbyId").format[String] and
(__ \ "hobbyName").format[String]
)(Hobby.apply, unlift(Hobby.unapply))
)(PersonWithHobby.apply, unlift(PersonWithHobby.unapply))