Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Noise free JSON format for sealed traits with Play 2.2 library

I need to get a simple JSON serialization solution with minimum ceremony. So I was quite happy finding this forthcoming Play 2.2 library. This works perfectly with plain case classes, e.g.

import play.api.libs.json._  sealed trait Foo case class Bar(i: Int) extends Foo case class Baz(f: Float) extends Foo  implicit val barFmt = Json.format[Bar] implicit val bazFmt = Json.format[Baz] 

But the following fails:

implicit val fooFmt = Json.format[Foo]   // "No unapply function found" 

How would I set up the alleged missing extractor for Foo?

Or would you recommend any other standalone library that handles my case more or less fully automatically? I don't care whether that is with macros at compile time or reflection at runtime, as long as it works out of the box.

like image 539
0__ Avatar asked Jun 10 '13 10:06

0__


1 Answers

AMENDED 2015-09-22

The library play-json-extra includes the play-json-variants strategy, but also the [play-json-extensions] strategy (flat string for case objects mixed with objects for case classes no extra $variant or $type unless needed). It also provides serializers and deserializers for macramé based enums.

Previous answer There is now a library called play-json-variants which allows you to write :

implicit val format: Format[Foo] = Variants.format[Foo] 

This will generate the corresponding formats automatically, it will also handle disambiguation of the following case by adding a $variant attribute (the equivalent of 0__ 's class attribute)

sealed trait Foo case class Bar(x: Int) extends Foo case class Baz(s: String) extends Foo case class Bah(s: String) extends Foo 

would generate

val bahJson = Json.obj("s" -> "hello", "$variant" -> "Bah") // This is a `Bah` val bazJson = Json.obj("s" -> "bye", "$variant" -> "Baz") // This is a `Baz` val barJson = Json.obj("x" -> "42", "$variant" -> "Bar") // And this is a `Bar` 
like image 133
Jean Avatar answered Sep 29 '22 22:09

Jean