我認爲有幾個不同的問題來解決這裏,所以我列出了三種不同的方法
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