【发布时间】:2014-11-16 19:47:28
【问题描述】:
我正在使用 json4s 在我的 Scala 代码中处理 JSON 对象。我想将 JSON 数据转换为内部表示。以下学习测试说明了我的问题:
"Polimorphic deserailization" should "be possible" in {
import org.json4s.jackson.Serialization.write
val json =
"""
|{"animals": [{
| "name": "Pluto"
| }]
|}
""".stripMargin
implicit val format = Serialization.formats(ShortTypeHints(List(classOf[Dog], classOf[Bird])))
val animals = parse(json) \ "animals"
val ser = write(Animals(Dog("pluto") :: Bird(canFly = true) :: Nil))
System.out.println(ser)
// animals.extract[Animal] shouldBe Dog("Pluto") // Does not deserialize, because Animal cannot be constructed
}
假设有一个包含动物列表的 JSON 对象。 Animal 是一种抽象类型,因此无法实例化。相反,我想解析 JSON 结构以返回 Dog 或 Bird 对象。他们有不同的签名:
case class Dog(name: String) extends Animal
case class Bird(canFly: Boolean) extends Animal
由于它们的签名不同,因此可以在 JSON 对象中没有类标记的情况下识别它们。 (准确地说,我收到的 JSON 结构没有提供这些标签)。
我尝试序列化 Animal 对象的列表(参见代码)。结果是:Ser: {"animals":[{"jsonClass":"Dog","name":"pluto"},{"jsonClass":"Bird","canFly":true}]}
可以看到,在序列化的时候,json4s添加了class-tagjsonClass。
如何反序列化不提供此类标签的 JSON 对象?是否可以通过扩展 TypeHints 来实现?
我还发现了一个类似的问题:[json4s]:Extracting Array of different objects 的解决方案以某种方式使用泛型而不是子类化。但是,如果我理解正确,此解决方案不允许简单地传递 json 对象并具有内部表示。相反,我需要选择不是None 的表单(同时检查继承层次结构中的所有可能类型。这有点乏味,因为我在 JSON 结构中具有不同深度的多个多态类。
【问题讨论】:
-
你找到答案了吗?我在这里面临同样的挑战......
-
很遗憾,我没有找到答案。作为一种解决方法,我同意创建序列化 JSON 以添加类型提示的人的意见;但是如果你不能影响 JSON 方案,这显然不是一个解决方案。我仍然对答案感兴趣,并且对 json4s 的了解比撰写问题时更多,因此我将尝试提出解决方案。
-
@borck 感谢您提出这个问题。我发现扩展
CustomSerializer是一个相当简单的解决方案(尽管用于提取大型多态结构的代码可能会变得有点臃肿)。我希望这也能帮助您解决问题。