unpickling json into a case class with option

466 Views Asked by At

Consider this case class:

case class Sample(status: String, message: Option[String])

Sample(status="OK") is serialized by play-json to JSON as

{
   "status":"OK"
}

and Sample(status="OK", message=Some("message content"))

{
   "status":"OK",
   "message":"message content"
}

This is how optional fields behave in Play and elsewhere in the JS world and typescript. For example I can easily cast the above json into an interface like this in Typescript:

interface Sample {
    status: string;
    message?: string;
}

const sample: Sample = { status: "OK" } as Sample;

Now I understand that there are a number of pickling concepts that serialize/deserialize in a consistent manner. However it's interesting that no pickling library supports this kind of deserialization into case class with ease. Maybe I am missing something.. Any recommendations?

UPDATE -- this is the behavior i would like to observe

json:

{ "status": "OK" }  

becomes:

Sample("OK",None)

json:

{ "status": "OK", "message": "message content" }  

becomes:

Sample("OK",Some("message content"))

Yes, indeed the following code can achieve this. But I don't want to explicitly specify this kind of distinction at many different places.

import upickle.default.Reader

case class Sample(status: String, message: Option[String])

implicit def r: Reader[Sample] = Reader[Sample] {
  case (x:upickle.Js.Value) =>
    Sample (
      status   = x.obj.get("status").get.toString(),
      message  = x.obj.get("message").flatMap(x => Some(x.toString))
    )
}

upickle.default.readJs[Sample](upickle.json.read(jsonText))
0

There are 0 best solutions below