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

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();
    }
}

关键细节说明

  1. 启用请求体缓冲:EnableBuffering()是必须的,因为默认情况下Request.Body是一个不可重读的流,读完一次后指针就到末尾了,后续模型绑定会读不到内容。启用缓冲后可以多次读取。
  2. 重置流位置:读取完原始JSON后,一定要把Request.Body.Position重置为初始值,否则后续的模型绑定(反序列化)会失败。
  3. 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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 11:11:06