skip to Main Content
 {
   "TestObjects": [
     {"the": "goal"},
     {"is": "to"},
     {"deserialize": "this"},
     {"simple": "array"},
     {"of": "objects"},
     {"into": "a"},
     {"C#": "Dictionary"}
    ]
}

Using .NET System.Text.Json. Seeking methodology to deserialize an array of objects where each object has two strings, as shown above, into a Dictionary<string, string>.

I have seen answers that describe deserializing into Dictionary<string, string>[] whereby each object is placed in a distinct Dictionary<string, string>, and that works. E.g. Ten objects results in an array of ten dictionaries. Example below works:

public class TestClass
{
    public Dictionary<string, string>[] TestObjects { get; set; }
}

var stream = File.OpenRead(@"C:testtest.json");

TestClass result = JsonSerializer.Deserialize<TestClass>(stream);

So, referring to the above example that works, the goal is to deserialize into a C# property of the form
Dictionary<string, string> TestObjects { get; set; } as opposed to
Dictionary<string, string>[] TestObjects { get; set; }

Thank You

3

Answers


  1. you can convert an array to a dictionary

    Dictionary<string, string> result = JsonDocument.Parse(json)
                .RootElement.GetProperty("SimpleArray").EnumerateArray()
                .ToDictionary(x => x.EnumerateObject().FirstOrDefault().Name,
                            x => x.EnumerateObject().FirstOrDefault().Value.ToString());
    

    But remember the dictionary shoud have the unique keys, otherwise you will get an exception

    or if you want to deserialize to a class, you will need to write a json converter

    TestClass result = System.Text.Json.JsonSerializer.Deserialize<TestClass>(json);
    
    public class ToDictConverter : System.Text.Json.Serialization.JsonConverter<Dictionary<string, string>>
    {
        public override Dictionary<string, string> Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
        {
            if (reader.TokenType == JsonTokenType.StartArray)
            {
                var dict = new Dictionary<string, string>();
                while (reader.Read())
                {
                    if (reader.TokenType == JsonTokenType.EndArray) return dict;
                    if (reader.TokenType == JsonTokenType.PropertyName)
                    {
                        string propName = reader.GetString();
                        if (reader.Read()) dict.Add(propName, reader.GetString());
                    }
                }
            }
            return null;
        }
    
        public override void Write(Utf8JsonWriter writer, Dictionary<string, string> value, JsonSerializerOptions options)
        {
            throw new NotImplementedException();
        }
    }
    
    public class TestClass
    {
    
    [System.Text.Json.Serialization.JsonConverter(typeof(ToDictConverter))]
    public Dictionary<string, string> SimpleArray { get; set; }
    
    }
    
    Login or Signup to reply.
  2. In order for it to deserialize as a Dictionary, it would have to be in this format:

    {
      "TestObjects": {
        "the": "goal",
        "is": "to",
        "convert": "this",
        "simple": "array",
        "of": "objects",
        "into": "a",
        "C#": "Dictionary"
      }
    }
    

    You could, however, add another read-only property that converts the array of dictionaries into one dictionary.

    public class TestClass1
    {
        public Dictionary<string, string>[] TestObjects { get; set; }
    
        public Dictionary<string, string> TestObjectsDict
        {
            get
            {
                return TestObjects.Select(x => x.First()).ToDictionary(x => x.Key, x => x.Value);
            }
        }
    }
    
    Login or Signup to reply.
  3. You could use a simple converter.

    Decorate the Property with [JsonConverter(...)]:

    public class TestClass2 {
        [JsonConverter(typeof(ObjectsToDictionaryConverter))]
        public Dictionary<string, string> TestObjects { get; set; }
    }
    

    The custom converter reads each property and value from the array of objects and uses them as the Key and Value of a Dictionary.
    It’s assumed that all keys (Properties) have a different name.

    When the Utf8JsonReader gets to the end of the arrays, i.e., when [Utf8JsonReader].TokenType == JsonTokenType.EndArray, return the Dictionary:

    Note: there’s no real error checking here. I leave it to you, since you know what the real JSON contains.

    class ObjectsToDictionaryConverter : JsonConverter<Dictionary<string, string>> {
        public override Dictionary<string, string> Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) {
    
            if (reader.TokenType != JsonTokenType.StartArray) {
                throw new JsonException($"Array of objects expected. Got {reader.TokenType}");
            }
    
            var dict = new Dictionary<string, string>();
            while (reader.Read()) {
                if (reader.TokenType == JsonTokenType.EndArray) break;
    
                if (reader.TokenType == JsonTokenType.StartObject) {
                    reader.Read();
                    string key = reader.GetString();
                    reader.Read();
                    string value = reader.GetString();
                    dict.Add(key, value);
                }
            }
            return dict;
        }
    
        public override void Write(Utf8JsonWriter writer, Dictionary<string, string> value, JsonSerializerOptions options) {
            throw new NotImplementedException();
        }
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search