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

如何在System.Text.Json中使用Reflection.Emit.ModuleBuilder反序列化JSON文档

如何在System.Text.Json中使用Reflection.Emit.ModuleBuilder反序列化JSON文档

我完全理解你现在的困扰——之前用Newtonsoft.Json配合动态生成的Response_T类型反序列化大量数据时速度飞快,结果迁移到System.Text.Json(.NET Framework 4.8用的9.0.6 NuGet包)后,虽然能成功实例化动态类型,但所有字段全是null,这确实让人挠头。咱们来一步步解决这个问题:

问题根源

System.Text.Json和Newtonsoft.Json的默认行为有个关键差异:System.Text.Json默认只序列化/反序列化公共属性(Property),而你通过Reflection.Emit创建的动态类型用的是公共字段(Field)。这就是为什么所有字段都无法被正确赋值的核心原因。另外,System.Text.Json默认是区分JSON键和成员名称大小写的,这也可能是潜在的问题点。

解决方案

1. 配置JsonSerializerOptions,启用字段支持

首先要修改序列化配置,让System.Text.Json能够识别并处理公共字段:

var options = new JsonSerializerOptions
{
    // 关键:开启字段的序列化/反序列化支持
    IncludeFields = true,
    // 如果你的JSON键是驼峰命名(比如"status")而字段是 PascalCase(比如"Status"),启用这个选项忽略大小写
    PropertyNameCaseInsensitive = true
};

2. 修改反序列化代码(优化异步调用)

另外,建议用await替代.Result来调用异步方法,避免.NET Framework环境下可能出现的死锁问题。修改后的反序列化逻辑如下:

Response response = new Response();
Type dynamicResponseType = ResponseBuilder.CreateResponseType<T>();

using (var stream = await httpresponse.Content.ReadAsStreamAsync())
{
    // 传入配置好的options,反序列化到动态类型
    var x = await JsonSerializer.DeserializeAsync(stream, dynamicResponseType, options);
    
    // 读取字段值的逻辑和之前保持一致
    FieldInfo fi = dynamicResponseType.GetField("Status");
    response.Status = (Response.ResponseStatus)fi.GetValue(x);
    fi = dynamicResponseType.GetField("ErrorMessage");
    response.ErrorMessage = (string)fi.GetValue(x);
    fi = dynamicResponseType.GetField("ErrorDetails");
    response.ErrorDetails = (string)fi.GetValue(x);
    fi = dynamicResponseType.GetField("Logon");
    response.Logon = (Logon)fi.GetValue(x);
    fi = dynamicResponseType.GetField("Object");
    response.Object = fi.GetValue(x);
}

3. (可选)为动态字段添加JsonPropertyName特性(精准映射)

如果你的JSON键和动态字段名称完全不匹配(比如JSON里是"logon"而字段是"Logon",且不想启用大小写不敏感),可以在创建动态字段时手动添加JsonPropertyNameAttribute来做精准映射。修改ResponseBuilder.CreateResponseType<T>中的字段创建逻辑:

// 以Logon字段为例
fieldBuilder = typeBuilder.DefineField("Logon", typeof(Data.Logon), FieldAttributes.Public);
fieldBuilder.SetOffset(fieldOffset);
fieldOffset += IntPtr.Size;

// 添加JsonPropertyName特性,指定JSON中的键名
var jsonAttrType = typeof(System.Text.Json.Serialization.JsonPropertyNameAttribute);
var attrConstructor = jsonAttrType.GetConstructor(new[] { typeof(string) });
var attrBuilder = new CustomAttributeBuilder(attrConstructor, new object[] { "logon" });
fieldBuilder.SetCustomAttribute(attrBuilder);

验证效果

做完以上修改后,System.Text.Json就能正确识别动态类型的公共字段,并将JSON数据反序列化到对应的字段中了,速度应该能和之前用Newtonsoft.Json时持平。

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.08 08:44:51