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

基于JsonSerializerSettings确定JSON.Net属性映射的技术问询

好的,我来帮你拆解JSON.Net中这两个核心的属性映射问题,结合特性、配置的优先级和规则一步步说清楚:

1. 确定C#属性对应的JSON属性名称

JSON.Net的命名规则遵循特性优先、局部覆盖全局的逻辑,优先级从高到低是这样的:

  • 属性级[JsonProperty]特性:如果你的C#属性直接标注了[JsonProperty("自定义名称")],不管其他配置,最终的JSON属性名就是这个指定的字符串——这是最高优先级,完全覆盖其他规则。
  • 类级[JsonObject]命名策略:如果你的类标注了[JsonObject(NamingStrategyType = typeof(xxxNamingStrategy))](比如CamelCaseNamingStrategy、SnakeCaseNamingStrategy),那么没有单独加JsonProperty的属性,会用这个类级策略转换名称。
  • 全局JsonSerializerSettings的契约解析器:如果你的序列化配置里指定了ContractResolver(比如CamelCasePropertyNamesContractResolver,或者自定义的DefaultContractResolver并设置了NamingStrategy),那些既没有属性级特性、也没有类级策略的属性,会用这个全局策略生成JSON名称。
  • 特殊情况:DataContract特性:如果你的类标注了[DataContract],那么JSON.Net会优先尊重属性上的[DataMember(Name = "xxx")]指定的名称;如果没有DataMember,才会遵循上面的命名策略。
  • 忽略属性:如果属性标注了[JsonIgnore],这个属性不会被序列化,自然也就没有对应的JSON属性名称。

举个直观的例子:

[JsonObject(NamingStrategyType = typeof(KebabCaseNamingStrategy))]
public class User
{
    [JsonProperty("user_id")]
    public int Id { get; set; }

    public string FullName { get; set; }

    [JsonIgnore]
    public string Password { get; set; }
}

// 序列化配置
var settings = new JsonSerializerSettings
{
    ContractResolver = new CamelCasePropertyNamesContractResolver()
};

这个例子里:

  • Id对应的JSON名称是user_id(属性级特性优先)
  • FullName对应的是full-name(类级的短横线策略覆盖了全局的驼峰策略)
  • Password不会出现在JSON里(被忽略)

2. 判断JSON属性名称映射到哪个C#属性

反序列化的映射逻辑和序列化是反向的,但同样遵循特性优先、匹配规则明确的原则:

  • 精确匹配特性指定的名称:先找C#属性上[JsonProperty("JSON键名")]完全匹配的,或者类标注[DataContract]时[DataMember(Name = "JSON键名")]的属性,找到就直接映射。
  • 按命名策略反向转换匹配:如果没有精确匹配的,就用当前生效的命名策略把JSON键名转换成C#属性名称,再去类里找对应的属性。比如全局用驼峰策略,JSON里的fullName会转成FullName去匹配;如果是蛇形策略,full_name会转成FullName。
  • 大小写敏感性控制:默认情况下,JSON.Net的名称匹配是大小写不敏感的;但如果你在ContractResolver里设置了IgnoreCase = false,就会严格区分大小写,比如JSON的fullname和C#的FullName就不会匹配。
  • 未匹配属性的兜底:如果类里有标注[JsonExtensionData]的属性(通常是Dictionary<string, object>类型),所有找不到对应C#属性的JSON键值对,都会被自动放到这个字典里,不会抛出反序列化错误。

举个反序列化的例子:

public class Product
{
    [JsonProperty("prod_id")]
    public int ProductId { get; set; }

    public string ProductName { get; set; }

    [JsonExtensionData]
    public Dictionary<string, object> Extra { get; set; }
}

// 待反序列化的JSON:{"prod_id":1, "productName":"Apple", "color":"Red"}

映射结果:

  • prod_id匹配到ProductId属性
  • productName(驼峰格式)匹配到ProductName(默认大小写不敏感+全局驼峰策略反向转换)
  • color没有对应的C#属性,会被放到Extra字典里

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 09:34:04