我们正在从Json.NET切换到ServiceStack.Text,我遇到了多态集合序列化的问题。
在JSON.NET中,我曾经创建了一个自定义的JsonCreationConverter并重写了Create()方法来选择我想要创建的类型 - 如下所示:
http://dotnetbyexample.blogspot.co.uk/2012/02/json-deserialization-with-jsonnet-class.html
有问题的集合是List<ItemBase>
,可以包含FlightItem
或CarHireItem
个对象。
这是我对JSON.NET的Create()方法的版本:
protected override ItemBase Create(Type objectType, JObject jsonObject)
{
var itemType = jsonObject["Type"].ToString();
switch (itemType)
{
case "flight":
return new FlightItem();
case "carhire":
return new CarHireItem();
default:
return null;
}
}
ServiceStack可以实现吗?
ServiceStack中的多态集合的序列化和反序列化工作正常,但它将对象类型附加到JSON输出,例如
"__type" : "TestProject.Model.FlightItem, TestProject"
这意味着我需要在发布JSON时提供类型,而且我不太热衷于在API调用中为任何人显示.NET类型。
有什么建议吗?如果可以用不同的方式做到这一点,你能指点我一些例子吗?
答案 0 :(得分:6)
首先,Interfaces or abstract types in DTOs are a bad idea。
您现在处于一个奇怪的位置,您正试图在DTO中支持多态类型,但是不想提供特定于JSON Serializer的信息?您需要定制代码来支持多态DTO的原因是因为根据有线格式无法确定应该使用哪种具体类型,因此为什么ServiceStack会为此目的发出 __ type 属性。
为了避免这些黑客攻击,并使其在所有JSON序列化程序中同样运行良好,最好将多态类型“扁平化”为单个“平面”DTO,然后通过线路发送。一旦你回到C#,你就可以使用代码将它投射到理想的类型中。
ServiceStack确实提供了一些JsConfig<ItemBase>.RawDeserializeFn
,可以让您做类似的事情,请参阅CustomSerializerTests for an example。还有JsConfig<ItemBase>.OnDeserializedFn
钩子可能有帮助,但它取决于ItemBase
是否包含两种具体类型的完整属性列表。