Custom Json Writes with combinators - not all case class fields are needed

I am trying to write a custom Json serializer in a game for the case class, but I do not want it to serialize all the fields of the class. I am new to Scala, so this is definitely a problem, but this is what I have tried so far:

case class Foo(a: String, b: Int, c: Double) 

Now, by default, this is done, as far as I saw in the examples:

 implicit val fooWrites: Writes[Foo] = ( (__ \ "a").write[String] and (__ \ "b").write[Int] (__ \ "c").write[Double] ) (unlift(Foo.unapply)) 

But what if I want to omit c from Json output? I have tried this so far, but it does not compile:

 implicit val fooWritesAlt: Writes[Foo] = ( (__ \ "a").write[String] and (__ \ "b").write[Int] ) (unlift({(f: Foo) => Some((fa, fb))})) 

Any help is much appreciated!

+7
source share
5 answers

If you are using Playframework 2.2 (not sure about earlier versions, but it should work as well), try the following:

 implicit val writer = new Writes[Foo] { def writes(foo: Foo): JsValue = { Json.obj("a" -> foo.a, "b" -> foo.b) } } 
+8
source share

What I usually do is convert the field to None and use writeNullable for it:

 implicit val fooWrites: Writes[Foo] = ( (__ \ "a").write[String] and (__ \ "b").write[Int] (__ \ "c").writeNullable[Double].contramap((_: Double) => None) ) (unlift(Foo.unapply)) 
+5
source share

Instead of specifying the combinator that creates the OWrites instance, you can directly build OWrites:

 val ignore = OWrites[Any](_ => Json.obj()) implicit val fooWrites: Writes[Foo] = ( (__ \ "a").write[String] and (__ \ "b").write[Int] and ignore ) (unlift(Foo.unapply)) 

This ignores any value of the case class at this position and simply always returns an empty JSON object.

+4
source share

This is very easy to do with Play JSON transformers:

 val outputFoo = (__ \ 'c).json.prune 

and then apply transform (outputFoo) to existing JsValue:

  val foo: Foo val unprunedJson: JsValue = Json.toJson(foo) unprunedJson.transform(outputFoo).map { jsonp => Ok(Json.obj("foo" -> jsonp)) }.recoverTotal { e => BadRequest(JsError.toFlatJson(e)) } 

see here http://mandubian.com/2013/01/13/JSON-Coast-to-Coast/

+2
source share

What version of the game are you using? fooWritesAlt compiles for me using 2.1.3. It should be noted that I needed to explicitly use the write object to write a partial JSON object, i.e.

 fooWritesAt.writes(Foo("a", 1, 2.0)) 

returns

 {"a": "a", "b": 2} 
0
source share

All Articles