Home > Software engineering >  Convert json into Dictionary automatically with Newtonsoft.Json
Convert json into Dictionary automatically with Newtonsoft.Json

Time:09-04

I have the json below

"Payload": {
    "AdditionalProperties": [
      {
        "Key": "MyKey1",
        "Value": "Value"
      },
      {
        "Key": "MyKey2",
        "Value": "Value"
      }
    ]
  }

By default this can be deserialized into an object with AdditionalProperties being deserialized into a List where AdditionalProperty just has 2 properties Key and Value - both strings

How can I get the json above to deserialize into a Dictionary<string, string> automatically?

At the moment I have had to create a separate property which isnt very nice

    public List<AdditionalProperty> AdditionalProperties { get; set; }

    public Dictionary<string, string> AdditionalPropertiesDictionary
    {
        get
        {
            return _additionalPropertiesDictionary ??= AdditionalProperties.ToDictionary(x => x.Key, x => x.Value);
        }
        set => _additionalPropertiesDictionary = value;
    }

Paul

CodePudding user response:

I usually create a JsonConstructor in this case

 Data data=JsonConvert.DeserializeObject<Data>(json);

 public class Data
 {
    public Payload Payload { get; set; }
 }
 public class Payload
 {
    public Dictionary<string,string> AdditionalProperties { get; set; }
    
    [JsonConstructor]
    public Payload(JArray AdditionalProperties)
    {
        this.AdditionalProperties = AdditionalProperties
                         .ToDictionary(ap => (string) ap["Key"],ap=>(string)ap["Value"] );
    }
 }

CodePudding user response:

You can write a custom converter to deserialize they key-value pairs:

public class ArrayStringDictionaryConverter : JsonConverter<Dictionary<string, string>>
{
    public override void WriteJson(JsonWriter writer, Dictionary<string, string> value, JsonSerializer serializer)
        => throw new NotImplementedException();

    public override Dictionary<string, string> ReadJson(JsonReader reader, Type objectType, Dictionary<string, string> existingValue, bool hasExistingValue, JsonSerializer serializer)
    {
        var keyValuePairs = serializer.Deserialize<IEnumerable<KeyValuePair<string, string>>>(reader);
        return new Dictionary<string, string>(keyValuePairs);
    }
}

Then you'd use it as the following:


var json = @"{ ""Payload"": {
    ""AdditionalProperties"": [
      {
        ""Key"": ""MyKey1"",
        ""Value"": ""Value""
      },
      {
        ""Key"": ""MyKey2"",
        ""Value"": ""Value""
      }
    ]
  }
 }";

var root = JsonConvert.DeserializeObject<Root>(json, new ArrayStringDictionaryConverter());

foreach(var (k, v) in root.Payload.AdditionalProperties)
{
    Console.WriteLine($"k: {k}, v: {v}");
}

// k: MyKey1, v: Value
// k: MyKey2, v: Value



public class Root
{
    public Payload Payload {get;set;}   
}

public class Payload
{
    public Dictionary<string, string> AdditionalProperties {get;set;}   
}

CodePudding user response:

You can write converter as below if you want

  public class Payload
  {
    [JsonConverter(typeof(AdditionalPropertiesConverter))]
    public Dictionary<string, string> AdditionalProperties { get; set; }
  }


public class AdditionalPropertiesConverter : JsonConverter<Dictionary<string, string>>
{

    public override void WriteJson(Newtonsoft.Json.JsonWriter writer, Dictionary<string, string>? value, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }

    public override Dictionary<string, string>? ReadJson(Newtonsoft.Json.JsonReader reader, Type objectType, Dictionary<string, string>? existingValue, bool hasExistingValue,
        JsonSerializer serializer)
    {
        var keyValuePairs = serializer.Deserialize<IEnumerable<KeyValuePair<string, string>>>(reader);
        return new Dictionary<string, string>(keyValuePairs);
    }
}

CodePudding user response:

To deserialise automatically with a dictionary you should have json structure like below.

 {
    "AdditionalProperties":
     {
        "MyKey1": ""Value",
        "MyKey2":"Value"
      }
 }
  • Related