如何获取ServiceStack以保留类型信息?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (41)

我正在使用ServiceStack将一些对象序列化和反序列化为JSON。考虑这个例子:

public class Container
{
    public Animal Animal { get; set; }
}

public class Animal
{
}

public class Dog : Animal
{
    public void Speak() { Console.WriteLine("Woof!"); }
}

var container = new Container { Animal = new Dog() };
var json = JsonSerializer.SerializeToString(container);
var container2 = JsonSerializer.DeserializeFromString<Container>(json);

((Dog)container.Animal).Speak(); //Works
((Dog)container2.Animal).Speak(); //InvalidCastException

最后一行抛出一个InvalidCastException,因为Properties字段实例化为动物类型,而不是dog类型。有什么方法可以告诉ServiceStack保留这个特定实例属于Dog类型的信息吗?

提问于
用户回答回答于

DTO中的继承是一个坏主意 - DTO应该尽可能自我描述,并且通过使用继承客户端有效地不知道服务最终会返回什么。这就是为什么你的DTO类在大多数“基于标准”的序列化器中无法正确地进行de / serialize的原因。

由于没有在JSON规范“类型信息”,概念才能继承的JSON序列化工作,他们需要发出专有扩展JSON wireformat包括这种类型的信息-现在将你的JSON有效载荷到一个特定的JSON序列化器实现。

ServiceStack的JsonSerializer将这个类型的信息存储在__type属性中,并且由于它可以大大增加负载,只会为需要它的类型发出此类型信息,即Interfaces,后期绑定object类型或abstract类。

有了这种说法,解决方案将变成Animal一个接口或一个抽象类,但建议不要在DTO中使用继承。

用户回答回答于

只序列化动物对象的属性,无论序列化对象是否为dog。即使你向dog类添加了一个公共属性,比如“name”,它也不会被序列化,所以当你反序列化时,将只拥有一个“动物”类的属性。

如果你将其更改为以下内容,它将有效;

public class Container<T> where T: Animal 
{        
    public T Animal { get; set; } 
}

public class Animal
{
}

public class Dog : Animal
{
    public void Speak() { Console.WriteLine("Woof!"); }
    public string Name { get; set; }
}

var c = new Container<Dog> { Animal = new Dog() { Name = "dog1" } };
var json = JsonSerializer.SerializeToString<Container<Dog>>(c);
var c2 = JsonSerializer.DeserializeFromString<Container<Dog>>(json);

c.Animal.Speak(); //Works
c2.Animal.Speak(); 

扫码关注云+社区