Newtonsoft JSON能否实现反序列化模型正确且序列化时修改属性名?
实现反序列化保留原名称,序列化修改属性名称的方案
当然可以做到!Newtonsoft.Json(Json.NET)提供了几种灵活的方式来实现这个需求——让模型在反序列化时匹配原始的JSON字段名,同时在序列化时输出自定义的属性名称。下面针对你的AccountingInspectionsResponseModel模型,给出两种实用方案:
方案一:使用自定义ContractResolver(推荐,无需修改模型结构)
这种方法不需要改动现有模型的JsonProperty特性,而是通过自定义契约解析器,在序列化阶段动态替换属性名称,反序列化时依然遵循原有的JsonProperty配置。
步骤1:定义自定义ContractResolver
public class CustomSerializationContractResolver : DefaultContractResolver { protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization) { JsonProperty property = base.CreateProperty(member, memberSerialization); // 根据属性名称映射序列化时的新名称,你可以按需修改这里的命名 switch (member.Name) { case nameof(AccountingInspectionsResponseModel.OrganizationInfo): property.PropertyName = "custom_organization_info"; break; case nameof(AccountingInspectionsResponseModel.Inspections): property.PropertyName = "custom_inspection_list"; break; // 其他需要改名的属性都可以在这里添加映射 } return property; } }
步骤2:序列化时使用自定义Resolver
当你需要序列化模型时,将自定义解析器传入JsonSerializerSettings即可:
var model = new AccountingInspectionsResponseModel { OrganizationInfo = new OrganizationInfo(), Inspections = new List<InspectionInfo>() }; // 序列化配置 var settings = new JsonSerializerSettings { ContractResolver = new CustomSerializationContractResolver(), Formatting = Formatting.Indented // 可选,让输出的JSON更易读 }; string serializedJson = JsonConvert.SerializeObject(model, settings);
而反序列化时直接用默认方式即可,完全不受影响:
string originalJson = "{\"subject_data\": {}, \"inspections\": []}"; var model = JsonConvert.DeserializeObject<AccountingInspectionsResponseModel>(originalJson);
方案二:拆分属性+JsonIgnore(适合简单场景)
如果你的模型结构不复杂,可以为每个需要改名的属性定义两个成员:一个用于反序列化(保留原JsonProperty),一个用于序列化(标记反序列化时忽略,指定新的JsonProperty),然后通过属性的get/set逻辑同步值。
修改后的模型示例:
public class AccountingInspectionsResponseModel { // 仅用于反序列化,序列化时忽略 [JsonProperty("subject_data")] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)] public OrganizationInfo OrganizationInfoDeserialized { get; set; } // 仅用于序列化,反序列化时忽略 [JsonProperty("custom_organization_info")] [JsonIgnore(Condition = JsonIgnoreCondition.WhenReading)] public OrganizationInfo OrganizationInfo { get => OrganizationInfoDeserialized; set => OrganizationInfoDeserialized = value; } // Inspections属性同理处理 [JsonProperty("inspections")] [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)] public List<InspectionInfo> InspectionsDeserialized { get; set; } [JsonProperty("custom_inspection_list")] [JsonIgnore(Condition = JsonIgnoreCondition.WhenReading)] public List<InspectionInfo> Inspections { get => InspectionsDeserialized; set => InspectionsDeserialized = value; } }
这种方式不需要额外的解析器,直接使用默认的序列化/反序列化方法即可,但会增加模型的代码量,适合属性较少的场景。
总结
- 如果模型属性较多,推荐使用自定义ContractResolver,保持模型简洁,逻辑集中;
- 如果是少量属性需要改名,拆分属性+JsonIgnore的方式更直接。
两种方案都能完美实现你的需求:反序列化时正确匹配原始JSON字段,序列化时输出你想要的属性名称。
内容的提问来源于stack exchange,提问作者Jaroslav Rumjakin




