0

I am trying to serialize and deserialize inheriting objects in a dictionary using JSON.net NewtonSoft.

In my program I have 3 classes setup A, B and C. Both B and C inherit A:

public class A
{
    public virtual string Value { get; } = "string";
}


public class B : A
{
    public override string Value => this.Score.ToString();

    public int Score { get; set; } = 5;
}

public class C : A
{
    public override string Value => this.AnotherScore.ToString();

    public int AnotherScore { get; set; } = 6;
}

In my code I create a dictionary which can story objects inheriting A and fill it with a B and a C object.

When I try using the objects in the dictionary, C# still knows the objects are of their type. (see code below)

But after serializing and deserializing, C# doesn't understand that it has to treat the B and C object in the dictionary as B and C objects.

static void Main(string[] args)
{
    // Create objects to store in dictionary
    B b = new B();
    A c = (A)new C(); 

    // Store objects in dictionary
    var dic = new Dictionary<string, A>();
    dic.Add("b", b);
    dic.Add("c", c);

    // C# still know the objects are of their type
    Console.WriteLine(dic["b"].Value);
    Console.WriteLine(dic["c"].Value);

    // Convert dictionary to JSON
    string serialized = JsonConvert.SerializeObject(dic, new JsonSerializerSettings()
    {
        Formatting = Formatting.Indented,
        PreserveReferencesHandling = PreserveReferencesHandling.Objects,
        TypeNameHandling = TypeNameHandling.Objects,
    });

    Console.WriteLine(serialized);

    // Convert json to dictionary
    var dic2 = JsonConvert.DeserializeObject<Dictionary<string, A>>(serialized);

    // C# doesn't know objects are of their type anymore
    Console.WriteLine(dic2["b"].Value);
    Console.WriteLine(dic2["c"].Value);




    Console.ReadKey();
}

Output:

5
6
{
  "$id": "1",
  "$type": "System.Collections.Generic.Dictionary`2[[System.String, mscorlib],[TestConsole.A, TestConsole]], mscorlib",
  "b": {
    "$id": "2",
    "$type": "TestConsole.B, TestConsole",
    "Value": "5",
    "Score": 5
  },
  "c": {
    "$id": "3",
    "$type": "TestConsole.C, TestConsole",
    "Value": "6",
    "AnotherScore": 6
  }
}
string
string

How do I let NewtonSoft know it should serialize the objects correctly with their correct type?

So that the last two write lines will write the same as the first two.

Joas
  • 1,796
  • 1
  • 12
  • 25
  • 3
    You have to use the same TypeNameHandling settings for the deserializer too, i guess... –  Mar 20 '18 at 22:39
  • @elgonzo Yeah noticed that right after posting the question, thanks for the help! – Joas Mar 20 '18 at 22:42
  • Possible duplicate of [how to deserialize JSON into IEnumerable with Newtonsoft JSON.NET](https://stackoverflow.com/questions/6348215/how-to-deserialize-json-into-ienumerablebasetype-with-newtonsoft-json-net) – Colin Young Mar 20 '18 at 22:42

1 Answers1

2

Passing the same settings to the DesirializeObject will solve this issue.

Sorry for bothering.

Joas
  • 1,796
  • 1
  • 12
  • 25