【问题标题】:JSON arrays and Scala SeqJSON 数组和 Scala Seq
【发布时间】:2015-12-23 12:44:05
【问题描述】:

我有像 class A(b:Seq[String]) 这样的 scala 类

我的问题是当我从没有b 字段的文本中反序列化它时,我的类包含null。是否可以强制去实化器填充空的Seq

我使用com.fasterxml.jackson.databind.ObjectMappercom.fasterxml.jackson.module.scala.DefaultScalaModule

编辑: 我想要解决所有这些字段而不明确提及它们的完整列表的解决方案。我正在更改所有声明。

【问题讨论】:

  • 您愿意使用其他 JSON 库吗?
  • 是的。我可以使用替代库。

标签: json scala deserialization


【解决方案1】:

我在使用 jackson 反序列化字符串数组时遇到了类似的问题,发现 jackson 显然(还没有尝试过)在 jackson-module 2.1.2 中修复了这个问题。它可能适用于 Seq。 https://github.com/FasterXML/jackson-module-scala/issues/48

【讨论】:

  • 我们使用 jackson-module-scala_2.11 版本 2.6.1
【解决方案2】:

如果您使用 Spray JSON,那么一个不处理 b 字段缺失的简单示例如下所示:

import spray.json._

case class A(b: Seq[String])

object Protocol extends DefaultJsonProtocol {
  implicit def aFormat = jsonFormat1(A)
}

import Protocol._

val str1 = """{ "b" : [] }""""
val str2 = """{ "b" : ["a", "b", "c"] }""""
val str3 = """{}"""
str1.parseJson.convertTo[A]//successful
str2.parseJson.convertTo[A]//successful
str3.parseJson.convertTo[A]//Deserialization error

在Spray JSON中,这可以通过为A类编写更详细的协议格式来解决:

import spray.json._

case class A(b: Seq[String])

object Protocol extends DefaultJsonProtocol {

  implicit object aFormat extends RootJsonFormat[A] {
    override def write(obj: A): JsValue = JsObject("b" -> obj.b.toJson)

    override def read(json: JsValue): A = json match {
      //Case where the object has exactly one member, 'b'
      case JsObject(map) if map.contains("b") && map.size == 1 => A(map("b").convertTo[Seq[String]])
      //Case where the object has no members
      case JsObject(map) if map.isEmpty => A(Seq())
      //Any other json value, which cannot be converted to an instance of A
      case _ => deserializationError("Malformed")
    }
  }
}

import Protocol._

val str1 = """{ "b" : [] }""""
val str2 = """{ "b" : ["a", "b", "c"] }""""
val str3 = """{}"""
str1.parseJson.convertTo[A]//successful
str2.parseJson.convertTo[A]//successful
str3.parseJson.convertTo[A]//successful

【讨论】:

  • 此解决方案需要明确指定Seq[?] 类型的所有字段。我有很多,希望他们都这样。
  • 你能举个具体的例子吗?是很多case类还是一个类有很多seq类型的成员?
  • 两者兼而有之。我有几个案例类,每个类都有多个 Seq 字段。
  • 如果我有 case class A(b: Seq[String])case class B(c: Seq[String]) 并且我试图反序列化 { } 我怎么知道要定位哪个案例类?
  • 我不知道杰克逊如何处理这种情况,但它与我的问题有什么关系?即使没有Seq 字段也会出现同样的问题
【解决方案3】:

很遗憾,Jackson 目前不支持此功能。

您可以在此处查看相关的 GitHub 票证:https://github.com/FasterXML/jackson-databind/issues/347

最好的办法是在类构造函数或访问器方法中将null 映射到一个空的Seq

class A(_b: Seq[String]) {
  val b = _b match {
    case null => Nil
    case bs => bs
  }
}

(其他选项另见https://stackoverflow.com/a/20655330/8261

【讨论】:

  • 此解决方案需要对Seg[?] 类型的每个字段进行更改。我想在一个地方解决问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-12-13
  • 1970-01-01
  • 2014-01-27
  • 2021-11-22
  • 1970-01-01
相关资源
最近更新 更多