-1

I have a class structure similar to this:

    // Parent class
    public class Circle
    {
        decimal Area { get; set; } = 0.2m;
    }

    // Child classes
    public class GreenCircle : Circle
    {
        string Color { get; set; } = "Green";
    }

    public class RedCircle : Circle
    {
        string Color { get; set; } = "Red";
    }

    public class BlueCircle : Circle
    {
        string Color { get; set; } = "Blue";
    }

    // Class to convert
    public class Shapes
    {
        public string ShapeType { get; set; } = "Circle";

        List<Circle> ShapeList { get; set; } = new List<Circle>
        {
            new RedCircle(),
            new BlueCircle(),
            new GreenCircle(),
        };
    }

I want to serialize/deserialize the Shapes class to json where the json string looks something like this:

{
  "shapeType": "circle",
  "shapeList": [
    {"name": "RedCircle",  "color": "red", "area": 0.2},
    {"name": "BlueCircle",  "color": "blue", "area": 0.2},
    {"name": "GreenCircle",  "color": "green", "area": 0.2}
  ]
}

I believe the way is to create a custom JsonConverter for it and I think I can manage the serialization part, but I have trouble deserializing the json:

  • How can I deserialize a json which has normal filed and array filed in it?
  • Is it possible to deserialize the list directly to the "child" objects? (i.e. to have a list with a RedCircle, BlueCircle and GreenCircle object instead of having a list with 3 Circle object)
Razero
  • 321
  • 1
  • 4
  • 16
  • "which has normal filed and array filed in it?" I don't understand what you're asking for here. – David L Feb 28 '23 at 16:53
  • By normal filed I meant something that converts to a basic type like string (e.g. shapeType) and by array filed I meant something that converts to for examplea list (e.g. shapeList). Basically how do I convert the example json to a `Shapes` object. – Razero Feb 28 '23 at 17:02
  • 1
    `TypeNameHandling` has security risks as explained in [TypeNameHandling caution in Newtonsoft Json](https://stackoverflow.com/q/39565954/3744182), especially when used globally in settings rather than applied to some property. Instead, see [Deserializing polymorphic json classes without type information using json.net](https://stackoverflow.com/q/19307752/3744182) for example converters. – dbc Feb 28 '23 at 17:07

1 Answers1

0

you can use TypeNameHandling option of Newtonsoft.Json

using Newtonsoft.Json

   Shapes shapes=new Shapes();
    
    var settings = new JsonSerializerSettings
    {
        TypeNameHandling = TypeNameHandling.Auto,
         ObjectCreationHandling = ObjectCreationHandling.Replace
    };
    string json = JsonConvert.SerializeObject(shapes,
                                  Newtonsoft.Json.Formatting.Indented, settings);

test

    shapes = JsonConvert.DeserializeObject<Shapes>(json, settings);

    foreach (var shape in shapes.ShapeList)
    {
        Console.WriteLine(shape.GetType().Name);
    }

test result

RedCircle
BlueCircle
GreenCircle

Pls pay your attention that I added ObjectCreationHandling.Replace, otherwise you will have a double collection. Plus fix ALL your classes by adding a public access modifier

public class Shapes
{
    public string ShapeType { get; set; } = "Circle";

    public List<Circle> ShapeList { get; set; } = new List<Circle>
        {
            new RedCircle(),
            new BlueCircle(),
            new GreenCircle(),
        };
}

the same for all your classes

UPDATE

Some smart pants will always tell it is not good to use Newtonsoft options, so if you trust them more then Newtonsoft and me, and love to do any work the hardest way possible, you can use this my answer without TypeNameHandling option

https://stackoverflow.com/a/70687842/11392290

Serge
  • 40,935
  • 4
  • 18
  • 45