1

This is my JSON object and C# class

   {
        "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"
            ]
        ]
    }

C# class

    public class Student
    {
        public string id { get; set; }
        public string name { get; set; }
        public string address { get; set; }
    }

is that possible to convert JSON into C# class list using JsonConvert or any other library without using loop?

Zulqarnain Jalil
  • 1,679
  • 16
  • 26
  • 3
    That is not valid json, secondly paste your valid json into a json to C# converter, then the answer becomes yes, with a little bit of massaging – TheGeneral Aug 25 '21 at 06:07
  • That class cannot be used with that JSON. At the very least, you need a different class with `List> rows` – OneCricketeer Aug 25 '21 at 06:11
  • 4
    https://dotnetfiddle.net/piqBpZ – TheGeneral Aug 25 '21 at 06:16
  • 1
    I would replace [] with {} – PawZaw Aug 25 '21 at 06:21
  • If your are using Visual Studio, copy the json content and use Menu: Edit -> Paste Special -> Paste JSON as Classes to create the classes – Kraego Aug 25 '21 at 06:56
  • Why this question is marked as negetive ? – Zulqarnain Jalil Aug 25 '21 at 07:30
  • @ZulqarnainJalil don't worry about it too much, the downvotes were likely because of the original incorrect json, here have a vote back – TheGeneral Aug 25 '21 at 07:32
  • As pointed by @TheGeneral l using System.Text.Json library is the way to go. The driving force behind introducing System.Text.Json with .Net Core 3.0 was performance and security. While they tried packaging Newtonsoft.Json inside .Net, they had some difficulties. Microsoft also wanted to remove the Newtonsoft.Json dependency from ASP.Net Core 3.0. More info here [link](https://inspiration.nlogic.ca/en/a-comparison-of-newtonsoft.json-and-system.text.json). – j4jada Aug 25 '21 at 08:17

2 Answers2

1

The conversion is pretty straightforward with Json.NET's JObject and Linq:

var students = JObject.Parse(json)["rows"] // Parse the JSON and get the "rows" property
    .Values<string[]>() // Get the property values as string arrays
    .Select(arr => new Student() { // Convert each string array to a Student object
        id = arr[0],
        name = arr[1],
        address = arr[2]
    }).ToList(); // Convert the IEnumerable<Student> to a List<Student>
Spencer Bench
  • 647
  • 4
  • 7
0

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;
    }
}
gjhommersom
  • 159
  • 1
  • 7