获取ServiceStack保留types信息

我使用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,因为Animal字段被实例化为一个Animaltypes,而不是一个Dogtypes。 有什么办法可以告诉ServiceStack保留这个特定的实例是Dogtypes的信息吗?

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

在DTO中有接口没有什么好的理由(在POCO模型中有很less的理由),使用接口来减less应用程序代码中耦合的货物崇拜习惯正在被不经意地泄漏到DTO中。 但是跨进程边界,接口只会增加耦合(它只是在代码中减less),因为消费者不知道要反序列化的具体types,所以它必须发出序列化特定的实现提示,现在将C#问题embedded到线程中C#命名空间将打破序列化),现在约束你的响应被特定的序列化器使用。 C#关注的漏洞违反了实现互操作性服务的核心目标之一。

由于在JSON规范中没有“types信息”的概念,为了inheritance在JSON序列化器中工作,他们需要向JSON wireformat 发出专有扩展以包含此types信息 – 现在将您的JSON负载耦合到特定的JSON序列化器的实现。

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

有了这个说法,解决的办法是将Animal改为Interface抽象类,但是build议不要在DTO中使用inheritance。

您只是序列化动物对象的属性,不pipe序列化对象是否为狗。 即使你添加一个公共属性到狗类,比如“Name”,它也不会被序列化,所以当你反序列化时,你只会拥有一个“Animal”类的属性。

如果你改变它以下它将工作;

 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(); 

也许是脱离主题,但Newtonsoft序列化程序可以做到这一点,包括选项:

  serializer = new JsonSerializer(); serializer.TypeNameHandling = TypeNameHandling.All; 

它将在json中创build一个名为$ type的属性,其中强types的对象。 当你调用反序列化器的时候,这个值将被用来以相同的types再次build立对象。 下一个testing使用强types的newtonsoft,而不是ServiceStack

  [TestFixture] public class ServiceStackTests { [TestCase] public void Foo() { FakeB b = new FakeB(); b.Property1 = "1"; b.Property2 = "2"; string raw = b.ToJson(); FakeA a=raw.FromJson<FakeA>(); Assert.IsNotNull(a); Assert.AreEqual(a.GetType(), typeof(FakeB)); } } public abstract class FakeA { public string Property1 { get; set; } } public class FakeB:FakeA { public string Property2 { get; set; } }