Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How setup spray-json to set null when json element is not present?

Here is spray-json example. Here is NullOptions trait.

The problem is when I declare a case class say

object MyJsonProtocol extends DefaultJsonProtocol  {
  implicit val some: RootJsonFormat[Some] = jsonFormat2(Some)
}

case class Some (
                name:String,
                age:Int
                )

and json do not contains a field for example:

{
    "name":"John"
}

I get: java.util.NoSuchElementException: key not found: age

So I have to add an Option and NullOption trait like that:

object MyJsonProtocol extends DefaultJsonProtocol with NullOptions  {
  implicit val some: RootJsonFormat[Some] = jsonFormat2(Some)
}

case class Some (
                name:String,
                age:Option[Int]
                )

Everything works. But I do not want to have a case classes where all member are Option. Is there a way to configure spray json unmarshalling to just set nulls without additional Option type?

P.S.

I understand that in general Option is better then null check, but in my case it is just monkey code.

Also complete example of marshalling during response processing is here

like image 366
Cherry Avatar asked Jan 19 '15 06:01

Cherry


People also ask

When serializing to JSON what happens if a property is null?

When serializing to JSON, if a value of a property in the data object is null, then it will be serialized as a JSON null. Non-existence of a property from the JSON data maps to an unset attribute in the data object space. If the property in the data object is not set (unset), then the property will not appear in the JSON data.

How to handle null and empty arrays and objects in JSON?

Handling JSON null and empty arrays and objects 1 Null values. JSON has a special value called null which can be set on any type of data including arrays, objects, number and boolean types. 2 Unset property. Non-existence of a property from the JSON data maps to an unset attribute in the data object space. ... 3 Empty property

What is null and unset in JSON?

JSON data has the concept of null and empty arrays and objects. This section explains how each of these concepts is mapped to the data object concepts of null and unset. JSON has a special value called null which can be set on any type of data including arrays, objects, number and boolean types.

Why does parse JSON return a null error?

The Parse JSON step with the above schema returns "Error - Expected String, received null" Replacing the EndDate data type "string" with "any" causes it to be unreadable in following steps (as though it was never parsed) and changing it to "data" causes an internal server error.


1 Answers

The only way I can think of is to implement your own Protocol via read/write, which might be cumbersome. Below is a simplified example. Note that I changed the age to be an Integer instead of an Int since Int is an AnyVal, which is not nullable by default. Furthermore, I only consider the age field to be nullable, so you might need to adopt as necessary. Hope it helps.

 case class Foo (name:String, age: Integer)

 object MyJsonProtocol extends DefaultJsonProtocol {
    implicit object FooJsonFormat extends RootJsonFormat[Foo] {
      def write(foo: Foo) =
        JsObject("name" -> JsString(foo.name),
                 "age"  -> Option(foo.age).map(JsNumber(_)).getOrElse(JsNull))

      def read(value: JsValue) = value match {
        case JsObject(fields) =>
          val ageOpt: Option[Integer] = fields.get("age").map(_.toString().toInt) // implicit conversion from Int to Integer
          val age: Integer = ageOpt.orNull[Integer]
          Foo(fields.get("name").get.toString(), age)
        case _ => deserializationError("Foo expected")
      }
    }
  }

  import MyJsonProtocol._
  import spray.json._

  val json = """{ "name": "Meh" }""".parseJson
  println(json.convertTo[Foo]) // prints Foo("Meh",null)
like image 102
edi Avatar answered Oct 06 '22 01:10

edi