一个很好的解决方案可能是进行多态反序列化。这允许您向您的 json 添加一个字段(如“类型”)并允许Jackson(假设您使用像 Jackson 这样的出色 json 解析器)代表您找出正确的类型。看起来你可能没有使用 Jackson;我保证它值得使用。
post 很好地介绍了多态类型。它涵盖了许多有用的情况,包括您无法修改 3rd 方代码的情况(这里您添加了一个 Mixin 来注释类型层次结构)。
最简单的情况最终看起来像这样(所有这些都适用于 Scala 对象——jackson even has a great scala module):
object Test {
@JsonTypeInfo(
use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.PROPERTY,
property = "type"
)
@JsonSubTypes(Array(
new Type(value = classOf[Cat], name = "cat"),
new Type(value = classOf[Dog], name = "dog")
))
trait Animal
case class Dog(name: String, breed: String, leash_color: String) extends Animal
case class Cat(name: String, favorite_toy: String) extends Animal
def main(args: Array[String]): Unit = {
val objectMapper = new ObjectMapper with ScalaObjectMapper
objectMapper.registerModule(DefaultScalaModule)
val dogStr = """{"type": "dog", "name": "Spike", "breed": "mutt", "leash_color": "red"}"""
val catStr = """{"type": "cat", "name": "Fluffy", "favorite_toy": "spider ring"}"""
val animal1 = objectMapper.readValue[Animal](dogStr)
val animal2 = objectMapper.readValue[Animal](catStr)
println(animal1)
println(animal2)
}
}
这会生成以下输出:
// Dog(Spike,mutt,red)
// Cat(Fluffy,spider ring)
您也可以避免列出子类型映射,但它要求 json "type" 字段有点复杂。尝试一下;你可能会喜欢它。像这样定义动物:
@JsonTypeInfo(
use = JsonTypeInfo.Id.CLASS,
include = JsonTypeInfo.As.PROPERTY,
property = "type"
)
trait Animal
它会像这样产生(和消费)json:
/*
{
"breed": "mutt",
"leash_color": "red",
"name": "Spike",
"type": "classpath.to.Test$Dog"
}
{
"favorite_toy": "spider ring",
"name": "Fluffy",
"type": "classpath.to.Test$Cat"
}
*/