Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Play JSON Combinators

In Play 2.1 we use something like below to get a Creature Object out of a JSON through reads.

implicit val creatureReads = (
  (__ \ "name").read[String] and
  (__ \ "isDead").read[Boolean] and
  (__ \ "weight").read[Float]
)(Creature.apply _)

Being relative new in Scala, I'm trying to understand if there is any other way to build the Creature object without using the Apply method? Would it be possible to have an anonymous function to create the object instead of relying on the apply?

I have use cases where most of the fields in my objects could be missing, but I would like to still build the object out of what I have. Is it better to just define one READ for the object and use readnullable for each of the fields?

I also could have complex conditionals, so would it be cleaner to just define custom functions to build it instead of trying to capture all cases in one Reader?

like image 460
James Cowhen Avatar asked Jul 23 '13 05:07

James Cowhen


People also ask

What is a JSValue?

You use the JSValue class to convert basic values, such as numbers and strings, between JavaScript and Objective-C or Swift representations to pass data between native code and JavaScript code.


1 Answers

Yes of course, the apply method is just a method that takes all the case classes' parameters. This roughly translates to the following:

implicit val creatureReads = (
  (__ \ "name").read[String] and
  (__ \ "isDead").read[Boolean] and
  (__ \ "weight").read[Float]
)((name: String, isDead: Boolean, weight: Float) => new Creature(name, isDead, weight))

For missing fields you should indeed use readNullable and wrap your classes fields to Option. If there are sensible defaults for your optional fields, you can use orElse(Reads.pure(value)) instead.

Let's say weight is optional and isDead is false by default:

implicit val creatureReads = (
  (__ \ "name").read[String] and
  (__ \ "isDead").read[Boolean].orElse(Reads.pure(false)) and
  (__ \ "weight").readNullable[Float]
)(Creature.apply _)

Sometimes you don't even want to read something from JSON. In that case, one possibility is passing the value explicitly:

def creatureReads(createdAt: DateTime) = (
  (__ \ "name").read[String] and
  (__ \ "isDead").read[Boolean].orElse(Reads.pure(false)) and
  (__ \ "weight").readNullable[Float] and
  (__ \ "createdAt").read(createdAt)
)(Creature.apply _)
like image 76
Marius Soutier Avatar answered Oct 10 '22 14:10

Marius Soutier