.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
相关产品推荐
相关产品推荐

