在 C# 的 JSON 反序列化中有效解除嵌套属性

问题描述 投票:0回答:1

作为 .NET 的新手,我正在学习在 C# 中使用 JSON 反序列化。如何有效地将具有嵌套属性的对象的 JSON 数组反序列化为 C# 实例列表,同时有效处理解除嵌套过程?

我有一个 JSON 数组,表示具有嵌套属性的对象列表,如下所示:

[
  {"name":"apple","properties":{"color":"red","flavor":"sweet"}},
  {"name":"orange","properties":{"color":"orange","flavor":"sour"}}
]

我想将此 JSON 反序列化为 C# 对象列表。 C# 类如下所示:

public class Fruit
{
    public string Name { get; set; }
    public string Color { get; set; }
    public string Flavor { get; set; }
}

需要注意的是,C# 对象(Fruit)的结构与 JSON 对象的结构不同。特别是,C# 对象没有“属性”变量。

是否有比手动迭代 JSON 数组元素并向 Fruit 对象赋值更有效的方法来实现此目的?

我的代码:

using System;
using System.Collections.Generic;
using System.Text.Json;

public class Fruit
{
    public string Name { get; set; }
    public string Color { get; set; }
    public string Flavor { get; set; }
}

class Program
{
    static void Main()
    {
        string json = "[{\"name\":\"apple\",\"properties\":{\"color\":\"red\",\"flavor\":\"sweet\"}},{\"name\":\"orange\",\"properties\":{\"color\":\"orange\",\"flavor\":\"sour\"}}]";

        // Deserialize into a list of Fruit objects
        List<Fruit> fruits = new List<Fruit>();

        var options = new JsonSerializerOptions
        {
            PropertyNameCaseInsensitive = true
        };

        var jsonObjects = JsonSerializer.Deserialize<List<JsonElement>>(json, options);
        
        foreach (var jsonObject in jsonObjects)
        {
            var fruit = new Fruit
            {
                Name = jsonObject.GetProperty("name").GetString(),
                Color = jsonObject.GetProperty("properties").GetProperty("color").GetString(),
                Flavor = jsonObject.GetProperty("properties").GetProperty("flavor").GetString()
            };

            fruits.Add(fruit);
        }

        // Print the fruits
        foreach (var fruit in fruits)
        {
            Console.WriteLine("Name: " + fruit.Name);
            Console.WriteLine("Color: " + fruit.Color);
            Console.WriteLine("Flavor: " + fruit.Flavor);
            Console.WriteLine();
        }
    }
}
c# json asp.net-core deserialization system.text.json
1个回答
0
投票

您有多种方法可以做到这一点。我想我会为此使用自定义转换器,因为:

  1. 它使用Utf8JsonReader(内存效率更高,特别是在大文件中)
  2. 更干净,你的逻辑被封装在一个地方

public class FruitConverter : JsonConverter<Fruit>
{
    public override Fruit Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        Fruit fruit = new Fruit();

        while (reader.Read())
        {
            if (reader.TokenType == JsonTokenType.EndObject)
            {
                return fruit;
            }

            if (reader.TokenType == JsonTokenType.PropertyName)
            {
                string propertyName = reader.GetString();
                reader.Read();
                switch (propertyName)
                {
                    case "name":
                        fruit.Name = reader.GetString();
                        break;
                    case "properties":
                        while (reader.Read() && reader.TokenType != JsonTokenType.EndObject)
                        {
                            if (reader.TokenType == JsonTokenType.PropertyName)
                            {
                                string prop = reader.GetString();
                                reader.Read();
                                if (prop == "color")
                                    fruit.Color = reader.GetString();
                                else if (prop == "flavor")
                                    fruit.Flavor = reader.GetString();
                            }
                        }
                        break;
                }
            }
        }
        throw new Exception("json is not fotmatted well");
    }

    public override void Write(Utf8JsonWriter writer, Fruit value, JsonSerializerOptions options)
    {
        writer.WriteStartObject();
        writer.WriteString("name", value.Name);
        writer.WriteStartObject("properties");
        writer.WriteString("color", value.Color);
        writer.WriteString("flavor", value.Flavor);
        writer.WriteEndObject();
        writer.WriteEndObject();
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.