Simon
Simon

Reputation: 6452

json writer for nested classes

I'm using Play! Scala 2.2 and I have a problem to render a class in Json :

I have two classes with one depending of the other, as following :

case class Artist(id: String, cover: String, website: List[String], link: String, Tracks: List[Track] = List())

case class Track(stream_url: String, title: String, artwork_url: Option[String] )

And their implicit Writers :

implicit val artistWrites: Writes[Artist] = Json.writes[Artist]

implicit val trackWrites: Writes[Track] = Json.writes[Track]

The writers work well as following :

println(Json.toJson(Track("aaa", "aaa", Some("aaa"))))
println(Json.toJson(Artist("aaa", "aaa", List("aaa"), "aaa", List())))

i.e if the Artist have an empty list of tracks. But if I want to do this :

println(Json.toJson(Artist("aaa", "aaa", List("aaa"), "aaa", List(SoundCloudTrack("ljkjk", "ljklkj", Some("lkjljk"))))))

I get an execution exception : [NullPointerException: null]

Can you please explain me what I am doing wrong?

Upvotes: 5

Views: 1302

Answers (2)

swapnil shashank
swapnil shashank

Reputation: 987

With Play 2.8, it is really simple to do, following works for me:

Let's suppose I had three classes:

case class InnerBean(fieldName: String, status: String, ruleCode: Int, subRuleCode: List[Int])

case class IntermediateBean(itemId: Long, innerBeanData: Option[List[InnerBean]])

case class OuterBean(uniqueTrackingId: String, intermediateBeanData: List[IntermediateBean])

implicit val innerBeanWrites: Writes[InnerBean] = Json.writes[InnerBean]
implicit val intermediateBeanWrites: Writes[IntermediateBean] = Json.writes[IntermediateBean]
implicit val outerBeanWrites: Writes[OuterBean] = Json.writes[OuterBean]

Upvotes: 0

Michael Zajac
Michael Zajac

Reputation: 55569

The problem is the initialization order. Json.writes[Artist] requires an implicit Writes[Track] in order to generate itself. The compiler is able to find the implicit Writes[Track], because you're declaring it in the same object, however trackWrites is initialized after artistWrites, which means that when Json.writes[Artist] is called, trackWrites is null. This doesn't interrupt the creation of artistWrites, however, so it goes unnoticed until it's actually used.

You can fix this by simply switching the initialization order, so that trackWrites is first.

Upvotes: 5

Related Questions