ASP.NET Core中如何获取JSON对象属性的实际数据类型
解决ActionFilter中获取原始JSON属性数据类型的方案
你的问题核心是模型绑定(反序列化)会提前把JSON转成CLR对象,导致无法拿到原始JSON的属性类型,解决思路是在模型绑定之前直接读取并解析原始请求体的JSON字符串,用Newtonsoft.Json的JObject来保留原始类型信息。
下面是具体的实现方案,我直接修改你的过滤器类来完成需求:
代码实现(基于IAsyncActionFilter)
因为读取请求体是异步操作,用IAsyncActionFilter比同步的IActionFilter更合适,代码如下:
using Microsoft.AspNetCore.Mvc.Filters; using Newtonsoft.Json.Linq; using System.IO; using System.Text; using System.Threading.Tasks; public class MyModelValidatorFilter : IAsyncActionFilter { public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next) { // 只处理JSON格式的请求,避免非JSON请求报错 if (context.HttpContext.Request.ContentType?.Contains("application/json") == true) { // 启用请求体缓冲,允许我们多次读取请求体(默认只能读一次) context.HttpContext.Request.EnableBuffering(); var originalBodyPosition = context.HttpContext.Request.Body.Position; try { // 读取原始JSON字符串 using var streamReader = new StreamReader( context.HttpContext.Request.Body, Encoding.UTF8, leaveOpen: true // 保持流打开,后续模型绑定还要用 ); var rawJson = await streamReader.ReadToEndAsync(); // 重置请求体的位置到开头,确保后续模型绑定能正常读取 context.HttpContext.Request.Body.Position = originalBodyPosition; if (!string.IsNullOrWhiteSpace(rawJson)) { // 解析原始JSON为JObject,这里会保留每个属性的原始JSON类型 var jsonObject = JObject.Parse(rawJson); // 遍历所有属性,获取原始数据类型 foreach (var property in jsonObject.Properties()) { // JToken.Type 会返回原始JSON类型:String/Integer/Boolean/Null/Array/Object等 var jsonPropertyType = property.Value.Type; // 这里可以根据你的需求处理类型信息,比如日志记录、自定义验证等 // 示例:打印属性名和对应的JSON类型 System.Console.WriteLine($"属性 [{property.Name}] 的原始JSON类型: {jsonPropertyType}"); } } } catch (System.Exception ex) { // 处理JSON解析异常(比如请求体不是合法JSON) System.Console.WriteLine($"解析原始JSON失败: {ex.Message}"); } } // 继续执行后续的过滤器和Action逻辑 await next(); } }
关键细节说明
- 启用请求体缓冲:
EnableBuffering()是必须的,因为默认情况下Request.Body是一个不可重读的流,读完一次后指针就到末尾了,后续模型绑定会读不到内容。启用缓冲后可以多次读取。 - 重置流位置:读取完原始JSON后,一定要把
Request.Body.Position重置为初始值,否则后续的模型绑定(反序列化)会失败。 - JObject保留原始类型:
JObject.Parse解析出来的每个属性值是JToken,它的Type属性对应JSON标准中的数据类型,完全符合你想要的“原始JSON属性类型”需求,不会被转成CLR类型(比如不会把JSON的数字统一转成int/long)。
额外注意事项
如果你的项目是ASP.NET Core 3.0+,默认使用的是System.Text.Json作为序列化器,但只要你项目中引用了Newtonsoft.Json(通常通过AddNewtonsoftJson()配置),上面的代码就能正常工作。如果没有引用,需要先安装Newtonsoft.Json NuGet包。
内容的提问来源于stack exchange,提问作者mnu-nasir
相关产品推荐
相关产品推荐

