我认为有几个不同的问题来解决这里,所以我列出了三种不同的方法
TL; DR
要么正确使用杰克逊多态性或,你的情况,去到一个更简单的方法,并消除多态的需要米请参阅我的code on github。
1.定制解串器
格式化后的JSON是:
{ inventory:
[ { productType: 'someProduct1',
details:
{ productId: 'Some_id',
description: 'some description' } },
{ productType: 'someProduct2',
details:
{ productId: 'Some_id',
description: { someKey: 'somevalue' }
}
}
]
}
领域productType
是错误的,在我看来,但如果这个格式是一种严格的要求,那么你可以编写自己的解串器是查看productType
字段并实例化不同的具体类。
我不认为这将是最好的解决办法,所以我没有写代码示例,但我喜欢Joda date-time package作为自定义序列化的参考/反序列化
2.杰克逊多态性
你“VE分离Product
从ProductDetails
利用类型字段:
case class Product(productType:String,details:ProductDetails)
abstract class ProductDetails
我想你混淆如何杰克逊的多态数据类型的处理工作和复杂的类设计的结果。
也许您的业务规则要求产品具有“类型”,在这种情况下,我会将其命名为“kind”或其他非代码标签,并将其放入您称为ProductDetails
的内容中。
但是,如果“类型”被包含在试图获得类型多态性的工作中,那么它是不正确的。
我已经包含下面的Scala的杰克逊多态性的工作示例:
/**
* The types here are close to the original question types but use
* Jackson annotations to mark the polymorphic JSON treatment.
*/
import scala.Array
import com.fasterxml.jackson.annotation.JsonSubTypes.Type
import com.fasterxml.jackson.annotation.{JsonSubTypes, JsonTypeInfo}
@JsonTypeInfo(
use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.PROPERTY,
property = "type")
@JsonSubTypes(Array(
new Type(value = classOf[ProductDetailsSimple], name = "simple"),
new Type(value = classOf[ProductDetailsComplex], name = "complex")
))
abstract class Product
case class ProductDetailsSimple(productId: String, description: String) extends Product
case class ProductDetailsComplex(productId: String, description: Map[String, String]) extends Product
case class PolymorphicInventory(products: List[Product])
注意,我删除了Product
VS ProductDetails
区别,所以一个Inventory
现在只是作为Product
列表。我留下了名字ProductDetailsSimple
和ProductDetailsComplex
,但我认为他们应该重新命名。
实例:
val inv = PolymorphicInventory(
List(
ProductDetailsSimple(productId="Some_id", description="some description"),
ProductDetailsComplex(productId="Some_id", description=Map("someKey" -> "somevalue"))
)
)
val s = jsonMapper.writerWithDefaultPrettyPrinter().writeValueAsString(inv)
println("Polymorphic Inventory as JSON: "+s)
输出:
Polymorphic Inventory as JSON: {
"products" : [ {
"type" : "simple",
"productId" : "Some_id",
"description" : "some description"
}, {
"type" : "complex",
"productId" : "Some_id",
"description" : {
"someKey" : "somevalue"
}
} ]
}
3.删除多态性
我建议多态性此情况下,不需要在所有,并且该错误当他们真的是有着不同意图的领域时,试图使“描述”成为单个字符串或键/值映射。
也许这牵涉到数据遗留问题(在这种情况下看到自定义DESER建议),但如果数据是在你的控制,我投“去简单”:
case class Product(productId: String,
description: String="",
attributes: Map[String, String]=Map.empty)
case class PlainInventory(products: List[Product])
我的更“阶-rific”使用Option
以指示不存在的值,所以:
case class Product(productId: String,
description: Option[String]=None,
attributes: Option[Map[String, String]]=None)
实例:
val inv = PlainInventory(
List(
Product(productId="Some_id", description=Some("some description")),
Product(productId="Some_id", attributes=Some(Map("someKey" -> "somevalue")))
)
)
val s = jsonMapper.writerWithDefaultPrettyPrinter().writeValueAsString(inv)
println("Plain Inventory as JSON: "+s)
输出:
Plain Inventory as JSON: {
"products" : [ {
"productId" : "Some_id",
"description" : "some description"
}, {
"productId" : "Some_id",
"attributes" : {
"someKey" : "somevalue"
}
} ]
}
上github工作最少的代码。
你有这个工作吗? – NightWolf