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

C#反序列化含$特殊键JSON时$type字段无法映射类属性问题

问题原因
  • 特性使用错误:你代码中添加的[JsonPropertyName("$type")]是System.Text.Json序列化库的专属特性,而你调用的JsonConvert.DeserializeObject属于*Newtonsoft.Json(Json.NET)*库,该特性不会被Json.NET识别,无法完成属性映射。
  • 框架默认拦截$type字段:Json.NET内置了多态类型反序列化机制,默认会将JSON中名为$type的键作为类型元数据解析,不会将其作为普通属性映射到实体类,即使标记了正确特性也会被框架优先拦截。
  • 额外的结构不匹配问题:你的JSON中CustomerIsMarried节点的Value是布尔类型true,IsSuspicious是布尔类型false,和你当前实体类定义的string Value、缺失IsSuspicious属性的结构不匹配,即使解决$type映射问题也会抛出转换错误。
修复方案

1. 修正实体类定义

  • 引入Newtonsoft.Json命名空间,将所有[JsonPropertyName("$type")]替换为Json.NET专属的[JsonProperty("$type")]特性
  • 补全缺失的IsSuspicious属性
  • 将Value属性类型改为object,兼容字符串、布尔值两种类型的赋值

修正后的实体类代码如下:

using Newtonsoft.Json;
using System.Collections.Generic;

public class DocumentDTO
{
    public string Version { get; set; }
    public List<DocumentInfo> Documents { get; set; }
}

public class DocumentInfo
{
    public string DocumentState { get; set; }
    public DocumentData DocumentData { get; set; }
    public string DocumentAsBase64 { get; set; }
}

public class DocumentData
{
    public string Name { get; set; }
    [JsonProperty("$type")]
    public string type { get; set; }
    public List<DocumentField> Fields { get; set; }
}

public class DocumentField
{
    public string Name { get; set; }
    [JsonProperty("$type")]
    public string type { get; set; }
    public string SuspiciousSymbols { get; set; }
    public string RecognizedValue { get; set; }
    public object Value { get; set; }
    public bool? IsSuspicious { get; set; }
}

2. 修改反序列化配置

反序列化时传入自定义配置,将MetadataPropertyHandling设置为Ignore,告诉Json.NET不要将$type当做内置元数据处理,按普通字段映射即可:

string jsonText="{\"Version\":\"1.1\",\"Documents\":[{\"DocumentState\":\"Correct\",\"DocumentData\":{\"Name\":\"test\",\"$type\":\"Document\",\"Fields\":[{\"Name\":\"CustomerFullName\",\"$type\":\"Text\",\"SuspiciousSymbols\":\"0\",\"RecognizedValue\":\"\",\"Value\":\"\"},{\"Name\":\"CustomerBirthDate\",\"$type\":\"Text\",\"Value\":\"\"},{\"Name\":\"DocumentNumber\",\"$type\":\"Text\",\"SuspiciousSymbols\":\"0000000000\",\"RecognizedValue\":\"\",\"Value\":\"\"},{\"Name\":\"CustomerIsMarried\",\"$type\":\"Checkmark\",\"IsSuspicious\":false,\"Value\":true},{\"Name\":\"CustomerCounty\",\"$type\":\"Text\",\"Value\":\"\"},{\"Name\":\"CustomerArea\",\"$type\":\"Text\",\"Value\":\"\"},{\"Name\":\"CustomerAddress\",\"$type\":\"Text\",\"SuspiciousSymbols\":\"11000000\",\"RecognizedValue\":\"\",\"Value\":\"\"},{\"Name\":\"DocumentGUID\",\"$type\":\"Text\",\"Value\":\"\"},{\"Name\":\"DocumentProposalID\",\"$type\":\"Text\",\"Value\":\"\"},{\"Name\":\"DocumentCountry\",\"$type\":\"Text\",\"SuspiciousSymbols\":\"000\",\"RecognizedValue\":\"FRA\",\"Value\":\"FRA\"},{\"Name\":\"DocumentCurrency\",\"$type\":\"Text\",\"SuspiciousSymbols\":\"000\",\"RecognizedValue\":\"EUR\",\"Value\":\"EUR\"},{\"Name\":\"DocumentTo\",\"$type\":\"Text\",\"Value\":\"\"},{\"Name\":\"DocumentFrom\",\"$type\":\"Text\",\"Value\":\"\"},{\"Name\":\"DocumentTotalNumberOfPages\",\"$type\":\"Text\",\"SuspiciousSymbols\":\"0\",\"RecognizedValue\":\"1\",\"Value\":\"1\"}]}}]}";
var serializerSettings = new JsonSerializerSettings
{
    MetadataPropertyHandling = MetadataPropertyHandling.Ignore
};
var documentResult = JsonConvert.DeserializeObject<DocumentDTO>(jsonText, serializerSettings);
补充说明

如果你本身就是要使用Json.NET的多态反序列化能力,不需要手动读取$type的值,可以直接删掉实体类里的type属性,去掉上述自定义配置,Json.NET会自动根据$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.30 14:27:33