0

I have JSON string that looks like:

{
    "type": "group",
    "logicalOperator": "or",
    "conditions":[{
            "type": "condition",
            "metric": "CTR",
            "operator": ">=",
            "value": "123"
        },
        {
            "type": "group",
            "logicalOperator": "and",
            "conditions": [{
                "type": "condition",
                "metric": "CTR",
                "operator": ">=",
                "value": "123"
                }]
        }
    ]
}

I want to deserialize it into C# classes (using Newtonsoft.JSON). But the point that conditions can include group or condition make problem for me.

public class Group {
    public string logicalOperator { get; set; }
    public List<object> conditions { get; set; }
}

public class Condition {
    public string metric { get; set; }
    public string @operator { get; set; }
    public int value { get; set; }
}

How can I get rid of the List<object>? TIA!

  • Possible duplicate of [JSON.NET - Conditional Type Deserialization](https://stackoverflow.com/questions/7816780/json-net-conditional-type-deserialization) – ngeksyo Apr 14 '18 at 07:06
  • Please look at this, i have marked this as possible duplicate. Because your problem looks like conditional deserialization. https://stackoverflow.com/questions/7816780/json-net-conditional-type-deserialization – ngeksyo Apr 14 '18 at 07:06
  • Assuming you can use [tag:json.net], take a look at [Deserializing polymorphic json classes without type information using json.net](https://stackoverflow.com/q/19307752/3744182) and [How to implement custom JsonConverter in JSON.NET to deserialize a List of base class objects?](https://stackoverflow.com/q/8030538/3744182) – dbc Apr 14 '18 at 07:21
  • Possible duplicate of [How do I turn a C# object into a JSON string in .NET?](https://stackoverflow.com/questions/6201529/how-do-i-turn-a-c-sharp-object-into-a-json-string-in-net) – Murat Can OĞUZHAN Apr 14 '18 at 09:30

2 Answers2

0

First of all C# doesn’t deserialize json strings. C# can be used to invoke libraries which do.

Based on pure guesses I would go ahead and say you’re maybe using Newtonsoft.Json to do the deserializing although you might very well be using something else. Let’s take a step back.

If that were the case, then “getting rid” of List<object> would be your smallest concern. Actually being able to come up with instances which aren’t just empty, plain’ol System.Object instances would be your first challenge. That’s simply because telling the deserializer what your super (base) type is won’t even make them go look for possible subtypes since the subtypes of any type is an open set (anyone can take and reference your assembly and extend your class without you feeling anything).

Having a list of references of type System.Object each pointing towards instancesof type MyNamespace.Group or MyNamespace.Condition might look like a drag until you realize that having instances of MyNamespace.Group and the other is the actual challenge in this particular use case you’re describing.

Taking another step back, in OOP, whenever you want to store a list of possibly different types of instances and your language is strongly typed and provides some sort of generics (C# is included), you cannot have a generic argument for element type which is not implicitly assignable from each and every one of the specific types you want your instances to potentially be. In your case, object is compatible with more than Group and Condition. If that is your sole problem then you should simply create a 3rd class (let’s call it EitherGroupOrCondition) and make that the root of a naturally occurring class hierarchy (both Group and Condition should now extend EitherGroupOrCondition). Then you could turn your List<object> into a List<EitherGroupOrCondition>.

Going back to deserializing: You would need to look at JsonSerializerSettings.TypeNameHandling and it’s entourage of features.

You should consider the following prerequisites to achieving your goal:

  • understanding OOP thoroughly
  • understanding your particular Json deserializer’s capabilities (hopefully you’re using Newtonsoft.Json)

Both of these prerequisites take time and patience and I encourage you to go ahead and fill them and never work blindly, without understanding at least the proposed product surface of that which you are using.

Eduard Dumitru
  • 3,242
  • 17
  • 31
0

You have no issue:

public class YourType
{
    public ConditionType Type { get; set; }
    public string Metric { get; set; }
    public string Operator { get; set; }
    public int Value { get; set; }
    public string LogicalOperator { get; set; }

    public List<YourType> Conditions { get; set; }
}

public enum ConditionType
{
    Group,
    Condition
}

Then just deserialize it as normal

var result = JsonConvert.DeserializeObject<YourType>(yourJson);

You will end up with a single YourType class that has an enumerator Type that you can use to determine if its a group or condition.

If it is a condition, the properties are filled out.

If it is a group, your Conditions inner list contains the rest.

angelsix
  • 392
  • 1
  • 7