You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

System.Text.Json中XmlElementAttribute动态类型绑定的替代方案咨询

解决方案:自定义JSON转换器实现动态类型绑定

System.Text.Json没有提供和XmlElementAttribute完全对等的特性,要实现根据JSON属性名动态为ParentClass的Item属性分配对应类型的功能,需要自定义JsonConverter来处理序列化和反序列化逻辑。

实现步骤

1. 定义自定义转换器

创建继承自JsonConverter<ParentClass>的转换器类,在读取JSON时判断属性名并实例化对应类型;写入JSON时根据Item的类型输出对应属性名:

using System.Text.Json;
using System.Text.Json.Serialization;

public class ParentClassConverter : JsonConverter<ParentClass>
{
    public override ParentClass Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        if (reader.TokenType != JsonTokenType.StartObject)
        {
            throw new JsonException("JSON必须以对象开头");
        }

        var parent = new ParentClass();

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

            if (reader.TokenType != JsonTokenType.PropertyName)
            {
                continue;
            }

            string propertyName = reader.GetString()!;
            reader.Read();

            switch (propertyName)
            {
                case "Location":
                    parent.Location = reader.GetString();
                    break;
                case "Emp":
                    parent.Item = JsonSerializer.Deserialize<Employee>(ref reader, options);
                    break;
                case "Dept":
                    parent.Item = JsonSerializer.Deserialize<Department>(ref reader, options);
                    break;
                default:
                    reader.Skip();
                    break;
            }
        }

        return parent;
    }

    public override void Write(Utf8JsonWriter writer, ParentClass value, JsonSerializerOptions options)
    {
        writer.WriteStartObject();
        writer.WriteString("Location", value.Location);

        if (value.Item is Employee emp)
        {
            writer.WritePropertyName("Emp");
            JsonSerializer.Serialize(writer, emp, options);
        }
        else if (value.Item is Department dept)
        {
            writer.WritePropertyName("Dept");
            JsonSerializer.Serialize(writer, dept, options);
        }

        writer.WriteEndObject();
    }
}

2. 注册并使用转换器

在序列化或反序列化时,将自定义转换器添加到JsonSerializerOptions中即可:

反序列化示例

// 解析含Emp的JSON
string empJson = @"
{
    ""Location"": ""Chicago"",
    ""Emp"": {
        ""EmployeeID"":123,
        ""EmployeeName"":""Peter""
    }
}";

var options = new JsonSerializerOptions();
options.Converters.Add(new ParentClassConverter());

ParentClass empParent = JsonSerializer.Deserialize<ParentClass>(empJson, options);
// empParent.Item 为 Employee 类型,属性值正确

// 解析含Dept的JSON
string deptJson = @"
{
    ""Location"": ""NJ"",
    ""Dept"": {
        ""DepartmentID"":567,
        ""DepartmentName"":""IT""
    }
}";

ParentClass deptParent = JsonSerializer.Deserialize<ParentClass>(deptJson, options);
// deptParent.Item 为 Department 类型,属性值正确

序列化示例

// 序列化含Employee的ParentClass
var empParent = new ParentClass
{
    Location = "NY",
    Item = new Employee { EmployeeID = 456, EmployeeName = "Alice" }
};

string serializedEmp = JsonSerializer.Serialize(empParent, options);
// 输出JSON包含"Emp"属性

// 序列化含Department的ParentClass
var deptParent = new ParentClass
{
    Location = "LA",
    Item = new Department { DepartmentID = 890, DepartmentName = "HR" }
};

string serializedDept = JsonSerializer.Serialize(deptParent, options);
// 输出JSON包含"Dept"属性

扩展说明

如果后续需要支持更多类型,只需在转换器的Read和Write方法中添加对应的分支逻辑即可,扩展性较强。

内容的提问来源于stack exchange,提问作者Sravani Yadav

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 05:20:29