如何设置 Spray-JSON,在 JSON 元素不存在时将其设为 null?

6
这里是spray-json示例。这里是NullOptions特质。
问题出在当我声明一个case class的时候。
object MyJsonProtocol extends DefaultJsonProtocol  {
  implicit val some: RootJsonFormat[Some] = jsonFormat2(Some)
}

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

而 JSON 不包含一个示例字段:

{
    "name":"John"
}

我得到了一个错误信息:java.util.NoSuchElementException: key not found: age

所以我必须添加一个OptionNullOption trait,像这样:
object MyJsonProtocol extends DefaultJsonProtocol with NullOptions  {
  implicit val some: RootJsonFormat[Some] = jsonFormat2(Some)
}

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

一切都正常。但我不想有一个情况类,其中所有成员都是Option。是否有一种方法可以配置spray json解组,只需设置null而无需额外的Option类型?
P.S.
我知道通常Option比空检查更好,但在我的情况下,这只是猴子代码。
此外,在响应处理期间进行编组的完整示例在这里
2个回答

2

我能想到的唯一方法是通过read/write实现您自己的协议,这可能会很麻烦。以下是一个简化的示例。请注意,我将age更改为Integer而不是Int,因为IntAnyVal,默认情况下不可为空。此外,我仅认为age字段可为空,因此您可能需要根据需要进行调整。希望这可以帮到你。

 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)

1

看起来你运气不好

从你链接的文档中:

spray-json 会将缺失的可选成员以及 null 的可选成员视为 None

你可以自定义 Json 的写入,但不能自定义 Json 的读取。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接