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

.NET 6 ASP.NET Core中Page/Field泛型对象的JSON序列化反序列化问题

解决方案:基于Json.NET实现多态Field的Page对象序列化与反序列化

1. 安装NuGet包

优先选择Newtonsoft.Json(Json.NET),它对多态类型的序列化支持更灵活,能解决子类属性无法正确序列化的问题:

Install-Package Newtonsoft.Json

2. 定义Field相关模型

采用抽象基类+子类的结构,通过Json.NET的特性标记多态关系,同时适配不同类型的Value属性:

using Newtonsoft.Json;
using Newtonsoft.Json.Converters;

// 标记多态转换规则,通过FieldType字段区分子类
[JsonConverter(typeof(JsonSubtypes), nameof(FieldType))]
[JsonSubtypes.KnownSubType(typeof(StringField), FieldType.String)]
[JsonSubtypes.KnownSubType(typeof(NumberField), FieldType.Number)]
public abstract class Field
{
    public string Name { get; set; }
    // 用于区分字段类型的标识,序列化时自动携带
    public abstract FieldType FieldType { get; }
    // 抽象Value属性,子类实现具体类型
    public abstract object Value { get; set; }
}

// 字段类型枚举
public enum FieldType
{
    String,
    Number
}

public class StringField : Field
{
    public override FieldType FieldType => FieldType.String;
    // 字符串专属校验属性
    public int MaxLength { get; set; }
    // 具体的string类型Value
    public new string Value { get; set; }
    // 重写基类属性做类型适配
    public override object Value
    {
        get => Value;
        set => Value = value as string;
    }
}

public class NumberField : Field
{
    public override FieldType FieldType => FieldType.Number;
    // 数字专属校验属性
    public int Min { get; set; }
    public int Max { get; set; }
    // 具体的int类型Value
    public new int Value { get; set; }
    // 重写基类属性做类型适配
    public override object Value
    {
        get => Value;
        set => Value = value is int val ? val : throw new ArgumentException("无效的整数类型值");
    }
}

3. 定义Page对象

public class Page
{
    public string Name { get; set; }
    public List<Field> Fields { get; set; } = new List<Field>();
}

4. 控制器中实现序列化与反序列化

在DemoController中使用Json.NET处理序列化,确保子类属性被正确识别:

using Microsoft.AspNetCore.Mvc;

[ApiController]
[Route("api/[controller]")]
public class DemoController : ControllerBase
{
    [HttpGet]
    public IActionResult GetPage()
    {
        var page = new Page
        {
            Name = "用户信息页",
            Fields = new List<Field>
            {
                new StringField
                {
                    Name = "用户名",
                    MaxLength = 20,
                    Value = "张三"
                },
                new NumberField
                {
                    Name = "年龄",
                    Min = 18,
                    Max = 100,
                    Value = 25
                }
            }
        };

        // 序列化时自动保留子类专属属性
        var json = JsonConvert.SerializeObject(page, Formatting.Indented);
        return Content(json, "application/json");
    }

    [HttpPost]
    public IActionResult PostPage([FromBody] Page page)
    {
        // 反序列化后可直接识别具体子类类型
        if (page.Fields.FirstOrDefault(f => f.Name == "年龄") is NumberField ageField)
        {
            if (ageField.Value < ageField.Min)
            {
                return BadRequest("年龄不能小于最小值");
            }
        }

        return Ok(page);
    }
}

5. 关键说明

  • 多态处理:通过JsonSubtypes转换器,序列化时自动添加FieldType字段,反序列化时依据该字段识别具体子类,解决了抽象基类无法序列化子类属性的问题。
  • Value适配:子类通过new关键字定义强类型Value,同时重写基类的object类型Value做转换,既满足泛型类型要求,又保证序列化输出具体值。
  • 替代方案:若使用System.Text.Json,需配置JsonSerializerOptions的TypeInfoResolver添加多态映射,但Json.NET的实现更简洁直观。

序列化后的JSON示例

{
  "Name": "用户信息页",
  "Fields": [
    {
      "FieldType": "String",
      "MaxLength": 20,
      "Value": "张三",
      "Name": "用户名"
    },
    {
      "FieldType": "Number",
      "Min": 18,
      "Max": 100,
      "Value": 25,
      "Name": "年龄"
    }
  ]
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 20:17:08