1

I have the following piece of code creating an object and writing into a file and reading from that file and trying to deserialize it into the same object(The code may look pointless but I simplified the large code into a small sample code to highlight the issue):

internal class Program
{
    private static void Main(string[] args)
    {
        string filePath = Path.Combine(@"C:\Users\user1", "TestFile.txt");

        TemplateA templateA = new TemplateA();
        templateA.objectsList = new List<TemplateX>();

        TemplateX templateX = new TemplateX();
        templateX.property1 = "Sample Value X1";

        TemplateY templateY = new TemplateY();
        templateY.property1 = "Sample value Y1";
        templateY.property2 = "Sample value Y2";

        templateA.objectsList.Add(templateX);
        templateA.objectsList.Add(templateY);

        string json = JsonConvert.SerializeObject(templateA, Formatting.Indented);
        File.WriteAllText(filePath, json);

        string jsonString = File.ReadAllText(filePath);
        TemplateA templateACopy = JsonConvert.DeserializeObject<TemplateA>(jsonString);
    }
}

internal class TemplateA
{
    [JsonProperty(PropertyName = "objectsList")]
    public List<TemplateX> objectsList;
}


internal class TemplateX
{
    [JsonProperty(PropertyName = "property1")]
    public string property1;
}

internal class TemplateY : TemplateX
{
    [JsonProperty(PropertyName = "property2")]
    public string property2;
}

When I read back the same object templateA written to TextFile.txt into templateACopy, it is loosing the information of property Y2("Sample value Y2"). That is templateACopy has: templateACopy object contents

This can be corrected by manually checking the string if it has elements of Class TemplateY and deserializing with the appropriate object type. But is there a way to autodetect the object is of an inherited type and deserialize into the appropriate object by the Newtonsoft JsonConvert's functions itself? (It is not known prior whether the json string has objects of TemplateX or TemplateY type. This can change at runtime.)

5
  • Take a look at this. Commented Dec 28, 2015 at 20:41
  • TemplateA has no knowledge of or relation to/with TemplateY. You can add Y-Objects to the objectsList because they inherit from TemplateX Commented Dec 28, 2015 at 20:41
  • You can also enable TypeNameHandling.Auto, but it's going to produce non-standardized json, and embed the types in your output. That means that if you ever change the type names, your deserializer will fail. If that's acceptable, it is another option. This second answer discusses using this approach. Commented Dec 28, 2015 at 20:43
  • So, basically you can write a custom JsonConverter, or enable TypeNameHandling.Auto. Commented Dec 28, 2015 at 20:48
  • You can add a field to the TemplateA class which is the actual type. Then do something like: TemplateA templateACopy = JsonConvert.DeserializeObject<Type.GetType(json["actual_type"])>(jsonString); Commented Dec 28, 2015 at 21:03

1 Answer 1

1

Use a custom setting for List<baseType> to get the derived type serialized by specifying the TypeNameHandling to objects:

   var settings = new JsonSerializerSettings()
   {
      TypeNameHandling = TypeNameHandling.Objects
   };

   string json = JsonConvert.SerializeObject(templateA, settings);

   TemplateA templateACopy = 
            JsonConvert.DeserializeObject<TemplateA>(jsonString, settings);
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.