Home > database >  C# Json to class - with dynamic json data
C# Json to class - with dynamic json data

Time:10-24

I have the following JSON :

{
    "ruleName": "PhoneNumber",
    "ruleSetInput": [
        {
            "PersonCode": "85782",
            "PhoneTypeId": "1",
            "PhoneClassId": "0",
            "DiallingCode": "021",
            "PhoneNumber": "9321662",
            "Extension": "",
            "Status": "",
            "User": "2",
            "DateCapturd": ""
        }
    ]
}

The JSON won't always have the same fields in the ruleSetInput node. I need to map each value under ruleSetInput to a class with the following class:

 public class Parameter
    {
        public string Name { get; set; }
        public string Value { get; set; }

        [JsonIgnore]
        public int Type { get; set; }

    }

As an example Parameter would be a list, and contain a value of :

Name: "PersonCode", Value: "85782"

How can I dynamically create this mapping? I have tried NewtonSoft.JSON but the mapping will only work if my object I am deseiralizing has this exact structure.

CodePudding user response:

You could make ruleSetInput a Dictionary<string, string> and then construct your Parameter instances from the key-value pairs using ruleSetInput.Select(kv => new Parameter { Name = kv.Key, value = kv.Value }

CodePudding user response:

Solution 1: With JsonConverterAttribute

You can implement the JsonConverter logic:

  1. Iterate each JObject from JArray.

  2. Iterate each JProperty (key-value pair) from JObject.

  3. And add into the array of List<Parameter> type.

For RuleSetInput property, apply the JsonConverterAttribute.

using Newtonsoft.Json.Serialization;
using Newtonsoft.Json.Linq;
using System.Collections.Generic;
using System.Linq;

public class ParameterConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return (objectType == typeof(Parameter));
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        List<Parameter> parameters = new ();
        JArray jArray = JArray.Load(reader);

        foreach (JObject jObj in jArray)
        {
            foreach (JProperty jProp in (JToken)jObj)
            {
                parameters.Add(new Parameter
                {
                    Name = jProp.Name,
                    Value = jProp.Value.ToString()
                });
            }
            
        }
            
        return parameters;
    }

    public override bool CanWrite
    {
        get { return false; }
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
}

public class Rule
{
    public string RuleName { get; set; }
    
    [JsonConverter(typeof(ParameterConverter))]
    public List<Parameter> RuleSetInput { get; set; }
}
var rule = JsonConvert.DeserializeObject<Rule>(json);

Demo JsonConverterAttribute @ .NET Fiddle


Solution 2: With JsonConstructorAttribute

The implementation logic is the same, you can move the logic into the constructor by applying JsonConstructorAttribute.

public class Rule
{
    [JsonConstructor]
    public Rule(string ruleName, JArray ruleSetInput)
    {
        RuleName = ruleName;
        
        List<Parameter> parameters = new ();

        foreach (JObject jObj in ruleSetInput)
        {
            foreach (JProperty jProp in (JToken)jObj)
            {
                parameters.Add(new Parameter
                {
                    Name = jProp.Name,
                    Value = jProp.Value.ToString()
                });
            }
        }
        
        RuleSetInput = parameters;
    }
    
    public string RuleName { get; set; }
    
    public List<Parameter> RuleSetInput { get; set; }
}

Demo JsonContructorAttribute @ .NET Fiddle

  • Related