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

ASP.NET Core MVC实现Field子类的多态JSON反序列化

在ASP.NET Core MVC中实现Field子类的JSON多态反序列化

要解决父类Field反序列化为对应子类(TextField/Checkbox)的问题,核心是通过自定义JSON转换器,根据JSON中的type字段或value的类型来判断并实例化正确的子类。以下是两种主流序列化库的实现方案:


方案一:使用默认的System.Text.Json

1. 自定义Field转换器

创建继承自JsonConverter<Field>的转换器,实现根据type字段选择子类的逻辑:

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

public class FieldJsonConverter : JsonConverter<Field>
{
    public override Field Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        // 读取JSON为文档,便于提取属性
        using var doc = JsonDocument.ParseValue(ref reader);
        var root = doc.RootElement;

        // 获取type字段值
        if (!root.TryGetProperty("type", out var typeElement))
        {
            throw new JsonException("Field对象缺少必填的'type'属性");
        }
        var fieldType = typeElement.GetString();

        // 根据type匹配对应子类反序列化
        return fieldType switch
        {
            "text" => JsonSerializer.Deserialize<TextField>(root.GetRawText(), options),
            "checkbox" => JsonSerializer.Deserialize<Checkbox>(root.GetRawText(), options),
            _ => throw new JsonException($"不支持的Field类型:{fieldType}")
        };
    }

    public override void Write(Utf8JsonWriter writer, Field value, JsonSerializerOptions options)
    {
        // 序列化时自动识别实际子类类型
        JsonSerializer.Serialize(writer, value, value.GetType(), options);
    }
}

2. 注册转换器

有两种注册方式可选:

  • 方式一:在父类上标记特性(仅影响Field类型)
[JsonConverter(typeof(FieldJsonConverter))]
public class Field
{
    public string type { get; set; }
    public bool filledIn { get; set; }
}
  • 方式二:全局注册(影响所有Field类型的反序列化)
    在Program.cs中添加:
builder.Services.AddControllers()
    .AddJsonOptions(options =>
    {
        options.JsonSerializerOptions.Converters.Add(new FieldJsonConverter());
    });

3. 验证与使用

在控制器方法中,可通过类型判断处理不同子类:

public void ParseAndSave(Form myForm)
{
    foreach (var field in myForm.fields)
    {
        switch (field)
        {
            case TextField textField:
                // 处理文本字段:textField.value 为字符串类型
                break;
            case Checkbox checkbox:
                // 处理复选框:checkbox.value 为布尔类型
                break;
        }
    }
}

方案二:基于value类型判断(替代type字段)

如果不想依赖type字段,可通过value的JSON类型来判断子类,修改转换器的Read方法:

public override Field Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
    using var doc = JsonDocument.ParseValue(ref reader);
    var root = doc.RootElement;

    if (root.TryGetProperty("value", out var valueElement))
    {
        return valueElement.ValueKind switch
        {
            JsonValueKind.String => JsonSerializer.Deserialize<TextField>(root.GetRawText(), options),
            JsonValueKind.True or JsonValueKind.False => JsonSerializer.Deserialize<Checkbox>(root.GetRawText(), options),
            _ => throw new JsonException("无法通过value类型识别Field子类")
        };
    }
    throw new JsonException("Field对象缺少value属性");
}

方案三:使用Newtonsoft.Json(Json.NET)

如果项目依赖Newtonsoft.Json,可创建对应的转换器:

using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

public class FieldNewtonsoftConverter : JsonConverter<Field>
{
    public override Field ReadJson(JsonReader reader, Type objectType, Field existingValue, bool hasExistingValue, JsonSerializer serializer)
    {
        var jObject = JObject.Load(reader);
        var fieldType = jObject["type"]?.ToString();

        return fieldType switch
        {
            "text" => jObject.ToObject<TextField>(serializer),
            "checkbox" => jObject.ToObject<Checkbox>(serializer),
            _ => throw new JsonException($"不支持的Field类型:{fieldType}")
        };
    }

    public override void WriteJson(JsonWriter writer, Field value, JsonSerializer serializer)
    {
        serializer.Serialize(writer, value, value.GetType());
    }
}

全局注册方式:

builder.Services.AddControllers()
    .AddNewtonsoftJson(options =>
    {
        options.SerializerSettings.Converters.Add(new FieldNewtonsoftConverter());
    });

内容的提问来源于stack exchange,提问作者Eric Webb

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 01:15:30