If you have multiple json definitions that have the same headers/rows layout you could use this custom converter for the Newtonsoft.Json library.
Usage:
var input = "{\"header\":[\"id\",\"name\",\"address\"],\"rows\":[[\"ee1e9edd-a06b-3f8c-97f1-62878d04540d\",\"John Doe\",\"test address 1234\"],[\"ee1e9edd-a06b-3f8c-97f1-62878d04540d\",\"Jane Rock\",\"test address 12345\"]]}";
var studens = JsonConvert.DeserializeObject<List<Student>>(input, new MyConverter<Student>());
foreach (var student in students)
{
Console.WriteLine(student.name);
}
The converter looks like this:
public class MyConverter<T> : JsonConverter where T : new()
{
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
// Not required.
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
reader.Read(); // Read StartObject token.
var mapping = GetMapping(reader);
var result = GetObjects(reader, mapping);
reader.Read(); // Read EndObject token.
return result;
}
private Dictionary<int, string> GetMapping(JsonReader reader)
{
Dictionary<int, string> mapping = new();
// Advance to the first header definition.
reader.Read(); // Read PropertyName token (should be 'headers').
reader.Read(); // Read StartArray token.
int index = 0;
do
{
index++;
mapping[index] = reader.Value.ToString();
reader.Read(); // Advance to next array element.
}
while(reader.TokenType != JsonToken.EndArray);
reader.Read(); // Read EndArray token.
return mapping;
}
private List<T> GetObjects(JsonReader reader, Dictionary<int, string> mapping)
{
List<T> result = new();
// Advance to the first row definition.
reader.Read(); // Read PropertyName token (should be 'rows').
reader.Read(); // Read StartArray token.
do
{
result.Add(GetObject(reader, mapping));
}
while(reader.TokenType != JsonToken.EndArray);
reader.Read(); // Read EndArray token.
return result;
}
private T GetObject(JsonReader reader, Dictionary<int, string> mapping)
{
// The object is an array in json.
reader.Read(); // Read StartArray token.
int index = 0;
T result = new();
do
{
index++;
var propertyToFind = mapping[index];
// Set the value to a property with matching name if it exists.
result.GetType().GetProperty(propertyToFind)?.SetValue(result, reader.Value);
reader.Read(); // Advance to next array element.
}
while(reader.TokenType != JsonToken.EndArray);
reader.Read(); // Read EndArray token.
return result;
}
public override bool CanConvert(Type objectType)
{
return true;
}
}
> rows`
– OneCricketeer Aug 25 '21 at 06:11