Deserialization of ambiguous json

public abstract class A { public string Foo{ get; set; } } public class B : A { public string Marco{ get; set; } } public class C : A { public string Las{ get; set; } } public class D : A { public string Las{ get; set; } } public class SerializeMe { [XmlElement("b", typeof(B))] [XmlElement("c", typeof(C))] [XmlElement("d", typeof(D))] public A[] serializeProp { get; set; } } SerializeMe me = new SerializeMe(); me.serializeProp = new A[]{ new B(){ Foo = "bar", Marco = "polo" }, new C(){ Foo = "bar", Las = "Vegas" }, new D(){ Foo = "bar", Las = "Vegas" } }; 

XmlElement attributes control xml serialization, so this results in:

  <SerializeMe> <B><Foo>bar</Foo><Marco>polo</Marco></B> <C><Foo>bar</Foo><Las>Vegas</Las></C> <D><Foo>bar</Foo><Las>Vegas</Las></D> </SerializeMe> 

And if I wanted to add similar attributes for deserialization in json (using the Newtonsoft Json.Net library):

 {[ {"Foo":"bar", "Marco":"polo"}, {"Foo":"bar", "Las":"Vegas"}, {"Foo":"bar", "Las":"Vegas"} ]} 

However, unlike xml, it does not contain details about types, so it does not seem obvious to me that it will correctly identify the class for deserialization. Is there anyway the correct deserialization using the existing json structure, or do I need to change the json structure (and how best to do this).

I was thinking of redefining serialization so that it produces the following format:

 {[ {"class":"B", "object":{"Foo":"bar", "Marco":"polo"}}, {"class":"C", "object":{"Foo":"bar", "Las":"Vegas"}}, {"class":"D", "object":{"Foo":"bar", "Las":"Vegas"}} ]} 

Is there a better way?

+4
source share
1 answer

You can leave the nested "object"= and just use a string that is not a valid property name as the class identifier:

 {"Foo":"bar", "Marco":"polo", "$Class"="B"} 

JSON.net has a built-in TypeNameHandling function, created by json as follows:

 {"$type":"Tests.MessageWrapper2, Tests, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", "Headers":{"$type":"System.Collections.Hashtable, mscorlib, Version=2.0.0.0, Culture=neutral,PublicKeyToken=b77a5c561934e089","DeliverAt":"yesterday!"}, "Body":{"$type":"Tests.TestMessage1, Tests, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null","Id":893239} } 

Please note: if you use TypeNameHandling, json can create arbitrary types. This way, you may not want to deserialize json from an untrusted source.

+2
source

Source: https://habr.com/ru/post/1340051/


All Articles