相关文章推荐
刀枪不入的皮带  ·  pcap_loop() function ...·  4 天前    · 
刀枪不入的皮带  ·  Code Inside Blog | ...·  9 月前    · 
刀枪不入的皮带  ·  Python项目中import ...·  10 月前    · 
刀枪不入的皮带  ·  PySimpleGui ...·  10 月前    · 
销魂的大白菜  ·  pycharm报错:ModuleNotFou ...·  21 分钟前    · 
神勇威武的长颈鹿  ·  python ...·  21 分钟前    · 
会开车的企鹅  ·  python ...·  21 分钟前    · 

When we deserilize it we need somehow a “marker”-property and I use the “FooBarBuzz” property from the BaseFoo-class as my marker. If it contains “A”, then it is implementation “AFoo” and “B” for “BFoo”.

Serialize

The serialization part works as expected:

AFoo a = new AFoo();
a.FooBarBuzz = "A";
a.A = "Hello World";
BFoo b = new BFoo();
b.FooBarBuzz = "B";
b.B = "Hello World";
List<BaseFoo> allFoos = new List<BaseFoo>();
allFoos.Add(a);
allFoos.Add(b);
var result = JsonConvert.SerializeObject(allFoos);

Resulting Json:

Deserialize and boom…

If we continue now and just use the typical code we get a nice exception:

var test = JsonConvert.DeserializeObject<List<BaseFoo>>(result);

Exception:

Additional information: Could not create an instance of type ConsoleApplication6.BaseFoo. Type is an interface or abstract class and cannot be instantiated. Path ‘[0].A’, line 1, position 6.

Introducing a simple JsonConverter

The exception is pretty clear, because JSON.NET has no knowledge about our convention. The way to go* is to write a JsonConverter. I found a couple of implementations on StackOverflow, but this one seems to be the easiest and best option.

* Small Update based on the comment from Michael: JSON.NET can also include the TypeName in the JSON as a “$type” property. If this is not an issue for you, then just add the “TypeNameHandling.Auto” to the JsonSerializerSettings and it will work. In my actual scenario I want a clean JSON output, without JSON.NET magic. That’s the reason for the converter.

public class FooConverter : JsonConverter
    public override bool CanConvert(Type objectType)
        return (objectType == typeof(BaseFoo));
    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        JObject jo = JObject.Load(reader);
        if (jo["FooBarBuzz"].Value<string>() == "A")
            return jo.ToObject<AFoo>(serializer);
        if (jo["FooBarBuzz"].Value<string>() == "B")
            return jo.ToObject<BFoo>(serializer);
        return null;
    public override bool CanWrite
        get { return false; }
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        throw new NotImplementedException();

When we read the JSON we look for our “FooBarBuzz”-property and serialize it to the correct implementation.

Let’s use our new JsonConverter

Just create a new instance of the Converter and apply it to the DeserializeObject method and you are done.

JsonConverter[] converters = { new FooConverter()};
var test = JsonConvert.DeserializeObject<List<BaseFoo>>(result, new JsonSerializerSettings() { Converters = converters });

Easy, right?

The full sample can be viewed on GitHub

Written by Robert Muehsig

Software Developer - from Saxony, Germany - working on primedocs.io. Microsoft MVP & Web Geek. Other Projects: KnowYourStack.com | ExpensiveMeeting | EinKofferVollerReisen.de
 
推荐文章