简体   繁体   English

将 JSON 转换为 C# Object 数组

[英]Convert JSON to C# Object array

This is my JSON object and C# class这是我的 JSON object 和 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 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?是否可以使用JsonConvert或任何其他库而不使用循环将 JSON 转换为 C# class 列表?

The conversion is pretty straightforward with Json.NET 's JObject and Linq:使用Json.NETJObject和 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>

If you have multiple json definitions that have the same headers/rows layout you could use this custom converter for the Newtonsoft.Json library.如果您有多个具有相同标题/行布局的 json 定义,您可以将此自定义转换器用于 Newtonsoft.Json 库。

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;
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM