Coomanperson
Coomanperson

Reputation: 134

Parse JSON with indexes in property name to list

Dealing with a JSON response similar to this, some of these responses can be up to 500+ items.

{
    "name1": "Paul",
    "address1": "123 paul lane",
    "name2": "George",
    "address2": "123 george lane",
    "name3": "Howie",
    "address3": "123 howie lane"
}

I would like a way, preferably using some sort of JSON deserialization, to jam this into a list of the following object.

public class Person
{
    public string Name { get; set; }
    public string Address { get; set; }
}

I'm not opposed to writing a custom deserializer, but I am dealing with quite a few of these types of responses, and a reusable solution would be ideal here.

Upvotes: 0

Views: 392

Answers (1)

Stanislas
Stanislas

Reputation: 2020

That looks like a very badly formatted JSON indeed.

My approach would depend on how predictable the fields are in the JSON, but if it is an endless list of key-value pairs without a pattern, I'd probably try to convert it to exactly that.

Large JSON

Your approach will differ if the file is large or small, depending on how much memory you can afford to use for the parsing of this file.

Using Newtonsoft.Json

See Read JSON with JsonTextReader.

string json = "{\"name1\": \"Paul\",\"address1\": \"123 paul lane\",\"name2\": \"George\",\"address2\": \"123 george lane\",\"name3\": \"Howie\",\"address3\": \"123 howie lane\"}";
using var reader = new Newtonsoft.Json.JsonTextReader(new System.IO.StringReader(json));
while (reader.Read())
{
    switch (reader.TokenType)
    {
        case Newtonsoft.Json.JsonToken.PropertyName:
        case Newtonsoft.Json.JsonToken.String:
            Console.WriteLine($"{reader.TokenType} - {reader.Value}");
            break;
        default:
            Console.WriteLine($"Skipped: {reader.TokenType}");
            break;
    }
}

Using System.Text.Json

See Use Utf8JsonReader.

string json = "{\"name1\": \"Paul\",\"address1\": \"123 paul lane\",\"name2\": \"George\",\"address2\": \"123 george lane\",\"name3\": \"Howie\",\"address3\": \"123 howie lane\"}";
var data = System.Text.Encoding.UTF8.GetBytes(json);
var reader = new System.Text.Json.Utf8JsonReader(data);
while (reader.Read())
{
    switch (reader.TokenType)
    {
        case System.Text.Json.JsonTokenType.PropertyName:
        case System.Text.Json.JsonTokenType.String:
            Console.WriteLine($"{reader.TokenType} - {reader.GetString()}");
            break;
        default:
            Console.WriteLine($"Skipped: {reader.TokenType}");
            break;
    }
}

Output

Both examples above will output:

Skipped: StartObject
PropertyName - name1
String - Paul
PropertyName - address1
String - 123 paul lane
PropertyName - name2
String - George
PropertyName - address2
String - 123 george lane
PropertyName - name3
String - Howie
PropertyName - address3
String - 123 howie lane
Skipped: EndObject

Small JSON

Using Newtonsoft.Json

If the JSON file is small, you could parse the entire file into a JObject and iterate through it like that.

private static IEnumerable<KeyValuePair<string, string>> GetPairs()
{
    string json = "{\"name1\": \"Paul\",\"address1\": \"123 paul lane\",\"name2\": \"George\",\"address2\": \"123 george lane\",\"name3\": \"Howie\",\"address3\": \"123 howie lane\"}";
    var data = Newtonsoft.Json.Linq.JObject.Parse(json);
    foreach (var pair in data)
    {
        yield return new KeyValuePair<string, string>(pair.Key, pair.Value.ToString());
    }
}

An even better approach might be to use a JTokenReader, but I haven't used that before.

Using System.Text.Json

I believe the equivalent in System.Text.Json of Newtonsoft.Json.Linq.JObject is JsonDocument.
See Use JsonDocument for access to data.

Upvotes: 3

Related Questions