.NET中如何使用JsonConvert.DeserializeObject仅反序列化所需属性
两种基于JsonConvert的实现方案,无需使用JObject.Parse手动解析全量JSON
可以根据是否允许修改原有LinkedInUser类结构二选一:
方案1:自定义JsonConverter(无需修改原有LinkedInUser类,推荐)
完全不改动你已定义的LinkedInUser结构,仅新增一个转换器类即可实现适配:
第一步:编写自定义转换器
using Newtonsoft.Json; using Newtonsoft.Json.Linq; using project.DTOs.Models; public class LinkedInUserConverter : JsonConverter<LinkedInUser> { public override LinkedInUser ReadJson(JsonReader reader, Type objectType, LinkedInUser existingValue, bool hasExistingValue, JsonSerializer serializer) { var jsonObj = JObject.Load(reader); var user = new LinkedInUser(); // 解析FirstName:优先匹配首选 locale 对应的值,无匹配则取localized下第一个值 var firstNameNode = jsonObj["firstName"]; if (firstNameNode != null) { var localizedFirstName = firstNameNode["localized"] as JObject; var preferredLocale = firstNameNode["preferredLocale"]; string localeKey = $"{preferredLocale["language"]}_{preferredLocale["country"]}"; user.FirstName = localizedFirstName.TryGetValue(localeKey, out var firstNameVal) ? firstNameVal.ToString() : localizedFirstName?.First?.First?.ToString(); } // 解析LastName,逻辑同FirstName var lastNameNode = jsonObj["lastName"]; if (lastNameNode != null) { var localizedLastName = lastNameNode["localized"] as JObject; var preferredLocale = lastNameNode["preferredLocale"]; string localeKey = $"{preferredLocale["language"]}_{preferredLocale["country"]}"; user.LastName = localizedLastName.TryGetValue(localeKey, out var lastNameVal) ? lastNameVal.ToString() : localizedLastName?.First?.First?.ToString(); } // JSON多余字段会自动忽略,无需额外处理 return user; } public override void WriteJson(JsonWriter writer, LinkedInUser value, JsonSerializer serializer) { // 仅需反序列化场景可直接留空或抛出未实现异常 throw new NotImplementedException(); } }
第二步:反序列化时指定转换器
var linkedInUser = JsonConvert.DeserializeObject<LinkedInUser>( await GetData(token), new LinkedInUserConverter() );
方案2:扩展LinkedInUser类(无需额外开发转换器,完全不涉及JObject操作)
如果允许调整原有LinkedInUser的内部结构,可以通过嵌套属性映射+反序列化回调实现适配,调用方代码完全不用改:
using Newtonsoft.Json; using System.Runtime.Serialization; namespace project.DTOs.Models { public class LinkedInUser { [JsonIgnore] // 标记忽略,因为JSON对应字段是嵌套对象而非字符串 public string FirstName { get; set;} [JsonIgnore] public string LastName { get; set; } // 新增内部属性映射JSON的嵌套结构 [JsonProperty("firstName")] internal LinkedInNameDto FirstNameDto { get; set; } [JsonProperty("lastName")] internal LinkedInNameDto LastNameDto { get; set; } // 反序列化完成后自动执行赋值逻辑 [OnDeserialized] internal void OnDeserializedMethod(StreamingContext context) { if (FirstNameDto != null) { string localeKey = $"{FirstNameDto.PreferredLocale.Language}_{FirstNameDto.PreferredLocale.Country}"; FirstName = FirstNameDto.Localized.TryGetValue(localeKey, out var val) ? val : FirstNameDto.Localized.First().Value; } if (LastNameDto != null) { string localeKey = $"{LastNameDto.PreferredLocale.Language}_{LastNameDto.PreferredLocale.Country}"; LastName = LastNameDto.Localized.TryGetValue(localeKey, out var val) ? val : LastNameDto.Localized.First().Value; } } } // 内部辅助类,无需对外暴露 internal class LinkedInNameDto { public Dictionary<string, string> Localized { get; set; } public LinkedInLocaleDto PreferredLocale { get; set; } } internal class LinkedInLocaleDto { public string Country { get; set; } public string Language { get; set; } } }
调整完成后直接用你原来的反序列化代码即可:
var linkedInUser = JsonConvert.DeserializeObject<LinkedInUser>(await GetData(token));
内容的提问来源于stack exchange,提问作者Anna Dmytriv
相关产品推荐
相关产品推荐

