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

C# JsonConvert反序列化后输出JSON时$type改type无效怎么办

问题根因
  • 你在DocumentData和DocumentField类的type属性上标注的[JsonProperty(PropertyName = "$type")]是双向映射规则:反序列化时会将输入JSON中的$type字段值绑定到该属性,但序列化输出时也会强制将该属性对应的JSON字段名输出为$type,和你预期输出type的需求直接冲突。
  • 若你的序列化配置开启了TypeNameHandling(非None值),Newtonsoft.Json会自动额外生成$type字段用于多态类型标识,会进一步导致输出不符合预期。
修复步骤

1. 修改实体类

删除DocumentData和DocumentField类中type属性上的[JsonProperty(PropertyName = "$type")]特性,核心实体代码修改后如下:

public class DocumentData
{
    public string Name { get; set; }
    // 移除原[JsonProperty(PropertyName = "$type")]特性
    public string type { get; set; }
    public List<DocumentField> Fields { get; set; }
}
public class DocumentField
{
    public string Name { get; set; }
    // 移除原[JsonProperty(PropertyName = "$type")]特性
    public string type { get; set; }
    public string SuspiciousSymbols { get; set; }
    public string RecognizedValue { get; set; }
    public string Value { get; set; }
}

2. 调整反序列化逻辑

去掉特性后,直接反序列化无法读取输入JSON中$type字段的值,可根据业务场景选择以下两种处理方式:

轻量场景(值中不会出现"$type"字符串)

直接替换JSON文本中的键名,实现成本最低:

// 将输入JSON中所有键名$type替换为type,匹配实体属性名
string processedJson = jsonText.Replace("\"$type\"", "\"type\"");
DocumentDTO documentResult = JsonConvert.DeserializeObject<DocumentDTO>(processedJson);

严谨场景(避免误替换值内容)

通过JObject递归遍历节点替换键名,不会影响字段值中出现的$type文本:

JObject jsonObj = JObject.Parse(jsonText);
ReplaceJsonKey(jsonObj, "$type", "type");
DocumentDTO documentResult = jsonObj.ToObject<DocumentDTO>();

// 递归替换键名的辅助方法
void ReplaceJsonKey(JToken token, string oldKey, string newKey)
{
    if (token.Type == JTokenType.Object)
    {
        JObject obj = (JObject)token;
        foreach (var prop in obj.Properties().ToList())
        {
            if (prop.Name == oldKey)
            {
                obj.Add(newKey, prop.Value);
                prop.Remove();
            }
            ReplaceJsonKey(prop.Value, oldKey, newKey);
        }
    }
    else if (token.Type == JTokenType.Array)
    {
        foreach (var item in (JArray)token)
        {
            ReplaceJsonKey(item, oldKey, newKey);
        }
    }
}

3. 配置接口全局序列化规则

必须关闭Newtonsoft.Json自动生成类型元数据的配置,同时匹配你期望的小驼峰输出格式:

  • 若使用ASP.NET Web API 2,在WebApiConfig.cs中修改JSON格式化器配置:
config.Formatters.JsonFormatter.SerializerSettings = new JsonSerializerSettings
{
    // 完全关闭自动类型元数据输出,禁止自动生成$type字段
    TypeNameHandling = TypeNameHandling.None,
    // 配置小驼峰命名,匹配version、documents等输出格式要求
    ContractResolver = new CamelCasePropertyNamesContractResolver()
};
  • 若使用ASP.NET Core + Newtonsoft.Json,在服务注册阶段添加如下配置:
builder.Services.AddControllers()
    .AddNewtonsoftJson(options =>
    {
        options.SerializerSettings.TypeNameHandling = TypeNameHandling.None;
        options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
    });
效果验证

以上配置完成后,接口序列化输出时type属性会正常输出为type字段,不会再出现$type字段,和你给出的预期返回结果完全一致。

内容的提问来源于stack exchange,提问作者core_user

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 11:30:43