.NET 7 API如何移除JSON请求的data包装类实现单类参数绑定?
.NET 7 API 跳过外层data包装直接绑定到单个类的解决方案
方案一:使用JsonPropertyName指定嵌套路径(单个类场景)
.NET 7 默认使用 System.Text.Json 进行JSON序列化/反序列化,它支持通过点路径指定属性对应的JSON节点位置。你只需要将原来的 [DataMember] 替换为 [JsonPropertyName],并指定完整的嵌套路径即可:
using System.Text.Json.Serialization; public class ReserveRequest { [JsonPropertyName("data.productId")] public string ProductId { get; set; } [JsonPropertyName("data.dateTime")] public string DateTime { get; set; } [JsonPropertyName("data.bookingItems")] public List<BookingItem> BookingItems { get; set; } } public class BookingItem { [JsonPropertyName("category")] public string Category { get; set; } [JsonPropertyName("count")] public int Count { get; set; } }
控制器方法直接接收 ReserveRequest 即可完成绑定:
[HttpPost] public IActionResult Reserve([FromBody] ReserveRequest request) { // 业务逻辑处理 return Ok(); }
方案二:自定义JSON转换器(全局统一处理场景)
如果所有POST请求都带有外层 data 包装,推荐使用自定义JSON转换器,一次性解决所有类的绑定问题,无需逐个修改属性:
1. 实现转换器
using System.Text.Json; using System.Text.Json.Serialization; public class DataWrapperConverter<T> : JsonConverter<T> { public override T Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { using JsonDocument doc = JsonDocument.ParseValue(ref reader); // 提取外层的data节点 JsonElement dataElement = doc.RootElement.GetProperty("data"); // 将data节点内容反序列化为目标类型 return dataElement.Deserialize<T>(options); } public override void Write(Utf8JsonWriter writer, T value, JsonSerializerOptions options) { // 如果需要返回的JSON也带data包装,保留此方法;否则可以抛出NotImplementedException writer.WriteStartObject(); writer.WritePropertyName("data"); JsonSerializer.Serialize(writer, value, options); writer.WriteEndObject(); } }
2. 注册转换器
方式一:全局注册(所有指定类型生效)
在 Program.cs 中配置JSON选项:
builder.Services.AddControllers() .AddJsonOptions(options => { // 为ReserveRequest添加转换器 options.JsonSerializerOptions.Converters.Add(new DataWrapperConverter<ReserveRequest>()); // 如有其他需要处理的请求类,继续添加 // options.JsonSerializerOptions.Converters.Add(new DataWrapperConverter<AnotherRequest>()); });
方式二:单个类上标注(仅当前类生效)
直接在 ReserveRequest 类上添加转换器属性:
[JsonConverter(typeof(DataWrapperConverter<ReserveRequest>))] public class ReserveRequest { [JsonPropertyName("productId")] public string ProductId { get; set; } [JsonPropertyName("dateTime")] public string DateTime { get; set; } [JsonPropertyName("bookingItems")] public List<BookingItem> BookingItems { get; set; } }
注意事项
- 替换旧属性:.NET 7 默认使用
System.Text.Json,原代码中的[DataMember]是DataContractSerializer(WCF使用)的属性,不再适用,需替换为System.Text.Json.Serialization.JsonPropertyName。 - 异常处理:如果请求JSON中不存在
data节点,两种方案都会抛出异常,可根据需求在转换器中添加空值判断逻辑。
内容的提问来源于stack exchange,提问作者tadhg88
相关产品推荐
相关产品推荐

