locked
C# deserialize JSON array RRS feed

  • Question

  • User947362319 posted

    I have a json object that looks something like this, with an array of different objects:

    myObj = {
    "name":"John Doe",
    "inputrows": [
    { obj1... },
    { obj2... },
    { obj3.. }
    ]
    }

    so i did like this.
    public List<object> inputrows{ get; set; }

    But, can I do something like this? and how would I do it correct?

    public List<Contentrow> inputrows{ get; set; }

    public class Contentrow
    {
    public obj1row object1{ get; set; }
    public obj2row object2{ get; set; }
    public obj3row object3{ get; set; }
    }


    public class obj1row
    {
    public string Name { get; set; }
    public string Address { get; set; }
    }
    public class obj2row
    {
    public int? Image { get; set; }
    public string Url { get; set; }
    }
    public class obj3row
    {
    public string Type { get; set; }
    public DateTimeOffset Created { get; set; }
    }

    Im not ure how to do this the right way? 

    Friday, February 28, 2020 7:02 PM

Answers

  • User-1330468790 posted

    Hi, chanlo,

    I think your problem is about how to deserilize a Json string which contains a list with some different types of the instance which are deriving from a same parent class. 

    The JsonConvert (using Newtonsoft.Json;) does have the ability to deal with derived classes problem. However, it seems like you don't construct the class correctly.

    You have to complete two things to achieve your target:

    1.Construct the object correctly. In your code, you put three objects in Contentrow. That way, they will be treated as three properties rather than three objects in an array.

    2.You have to put the derived type information into Json string and turn on the "TypeNameHandling.All" to tell the converter to identify the type information.

    More information, you can refer to below code:

    Console App:

    namespace JsonSerialise
    {
        class Program
        {
            static void Main(string[] args)
            {
                //Json with type
                string myObj = "{ \"name\":\"John Doe\",\"inputrows\": " +
                                "[" +
                                "{\"$type\":\"JsonSerialise.obj1row, JsonSerialise\", \"Name\": \"name1\",\"Address\":\"address1\"}," +
                                "{\"$type\":\"JsonSerialise.obj2row, JsonSerialise\", \"Image\": 2,\"Url\":\"url1\" }," +
                                "{\"$type\":\"JsonSerialise.obj3row, JsonSerialise\",\"Type\": \"type1\",\"Created\":\"2020-3-2T00:00:00-05:00\" }" +
                                "]" +
                                "}";
    
    
                // Create an object
                obj1row obj1 = new obj1row { Name = "name1", Address = "address1" };
                obj2row obj2 = new obj2row { Image = 32, Url = "url1" };
                obj3row obj3 = new obj3row { Type="", Created = new DateTimeOffset(new DateTime(2020, 3, 2, 13, 32, 00), new TimeSpan(-5, 0, 0)) };
                List<Contentrow> list = new List<Contentrow>();
                list.Add(obj1);
                list.Add(obj2);
                list.Add(obj3);
                Result result1 = new Result();
                result1.name = "Joe";
                result1.inputrows = list;
    
                //Settings for JsonConvert
                var settings = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.All };
    
                // convert object to json
                string s = JsonConvert.SerializeObject(result1, Formatting.Indented, settings);
    
                // convert json to object
                Result result2 =(Result) JsonConvert.DeserializeObject<Result>(myObj, settings);
    
               
                Console.WriteLine(s);
                Console.WriteLine(result2.ToString());
    
                 Console.ReadKey();
    
            }
        }
    
        public class Result
        {
            public string name { get; set; }
            public List<Contentrow> inputrows { get; set; }
    
            //Printing stuff, not important
            public override string ToString()
            {
                StringBuilder sb = new StringBuilder();
                sb.Append("{name: " + name + ",");
                sb.Append("inputrows: [");
                foreach (Contentrow row in inputrows)
                {
                    sb.Append(row.ToString());
                }
                sb.Append("]}");
    
                return sb.ToString();
            }
        }
    
    
        public class Contentrow
        {
    
        }
    
        public class obj1row : Contentrow
        {
            public string Name { get; set; }
            public string Address { get; set; }
    
            public override string ToString()
            {
                return "{ Name: " + Name + ", Address: " + Address + "}";
            }
        }
        public class obj2row : Contentrow
        {
            public int? Image { get; set; }
            public string Url { get; set; }
            public override string ToString()
            {
                return "{ Image: " + Image + ", Url: " + Url + "}";
            }
        }
        public class obj3row : Contentrow
        {
            public string Type { get; set; }
            public DateTimeOffset Created { get; set; }
    
            public override string ToString()
            {
                return "{ Type: " + Type + ", Created: " + Created + "}";
            }
        }
    
    }

    Demo:

    Hope this can help you.

     

    Best regards,

    Sean

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Monday, March 2, 2020 8:45 AM

All replies

  • User-1330468790 posted

    Hi, chanlo,

    I think your problem is about how to deserilize a Json string which contains a list with some different types of the instance which are deriving from a same parent class. 

    The JsonConvert (using Newtonsoft.Json;) does have the ability to deal with derived classes problem. However, it seems like you don't construct the class correctly.

    You have to complete two things to achieve your target:

    1.Construct the object correctly. In your code, you put three objects in Contentrow. That way, they will be treated as three properties rather than three objects in an array.

    2.You have to put the derived type information into Json string and turn on the "TypeNameHandling.All" to tell the converter to identify the type information.

    More information, you can refer to below code:

    Console App:

    namespace JsonSerialise
    {
        class Program
        {
            static void Main(string[] args)
            {
                //Json with type
                string myObj = "{ \"name\":\"John Doe\",\"inputrows\": " +
                                "[" +
                                "{\"$type\":\"JsonSerialise.obj1row, JsonSerialise\", \"Name\": \"name1\",\"Address\":\"address1\"}," +
                                "{\"$type\":\"JsonSerialise.obj2row, JsonSerialise\", \"Image\": 2,\"Url\":\"url1\" }," +
                                "{\"$type\":\"JsonSerialise.obj3row, JsonSerialise\",\"Type\": \"type1\",\"Created\":\"2020-3-2T00:00:00-05:00\" }" +
                                "]" +
                                "}";
    
    
                // Create an object
                obj1row obj1 = new obj1row { Name = "name1", Address = "address1" };
                obj2row obj2 = new obj2row { Image = 32, Url = "url1" };
                obj3row obj3 = new obj3row { Type="", Created = new DateTimeOffset(new DateTime(2020, 3, 2, 13, 32, 00), new TimeSpan(-5, 0, 0)) };
                List<Contentrow> list = new List<Contentrow>();
                list.Add(obj1);
                list.Add(obj2);
                list.Add(obj3);
                Result result1 = new Result();
                result1.name = "Joe";
                result1.inputrows = list;
    
                //Settings for JsonConvert
                var settings = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.All };
    
                // convert object to json
                string s = JsonConvert.SerializeObject(result1, Formatting.Indented, settings);
    
                // convert json to object
                Result result2 =(Result) JsonConvert.DeserializeObject<Result>(myObj, settings);
    
               
                Console.WriteLine(s);
                Console.WriteLine(result2.ToString());
    
                 Console.ReadKey();
    
            }
        }
    
        public class Result
        {
            public string name { get; set; }
            public List<Contentrow> inputrows { get; set; }
    
            //Printing stuff, not important
            public override string ToString()
            {
                StringBuilder sb = new StringBuilder();
                sb.Append("{name: " + name + ",");
                sb.Append("inputrows: [");
                foreach (Contentrow row in inputrows)
                {
                    sb.Append(row.ToString());
                }
                sb.Append("]}");
    
                return sb.ToString();
            }
        }
    
    
        public class Contentrow
        {
    
        }
    
        public class obj1row : Contentrow
        {
            public string Name { get; set; }
            public string Address { get; set; }
    
            public override string ToString()
            {
                return "{ Name: " + Name + ", Address: " + Address + "}";
            }
        }
        public class obj2row : Contentrow
        {
            public int? Image { get; set; }
            public string Url { get; set; }
            public override string ToString()
            {
                return "{ Image: " + Image + ", Url: " + Url + "}";
            }
        }
        public class obj3row : Contentrow
        {
            public string Type { get; set; }
            public DateTimeOffset Created { get; set; }
    
            public override string ToString()
            {
                return "{ Type: " + Type + ", Created: " + Created + "}";
            }
        }
    
    }

    Demo:

    Hope this can help you.

     

    Best regards,

    Sean

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Monday, March 2, 2020 8:45 AM
  • User947362319 posted

    Thank you so much Sean, i will look at it and learn :D

    Monday, March 2, 2020 2:36 PM
  • User-1330468790 posted

    Hi, chanlo,

    I would be glad if it could help you.

    If you still meet problems, you can post it here and people here will be happy to solve the problem.

    If you find that the answer does solve your issues, I suggest you could mark the answer which is right and helpful. This will help other people who faces the same issue to find the right answer more faster.

    Best regards,

    Sean

    Tuesday, March 3, 2020 11:26 AM