在Newtonsoft.Json中反序列化时将子属性映射到类属性
Newtonsoft.Json中的[DataMember]
属性允许将原始JSON属性名称映射到类属性。但是,在某些情况下,可能需要将复杂JSON对象的子属性映射到类中的简单属性。
传统方法
如果只需要一个额外的属性,一种方法是将JSON解析为JObject,并使用ToObject()
和SelectToken()
来填充类并获取额外的属性。
考虑一个JSON对象,其中包含一个复杂的picture
属性,以及一个类,其中只需要picture.data.url
属性:
<code class="language-json">{ "picture": { "id": 123456, "data": { "type": "jpg", "url": "http://www.someplace.com/mypicture.jpg" } } }</code>
<code class="language-csharp">public class Person { [JsonProperty("name")] public string Name { get; set; } [JsonProperty("age")] public string Age { get; set; } public string ProfilePicture { get; set; } } string json = @"{...}"; JObject jo = JObject.Parse(json); Person p = jo.ToObject<Person>(); p.ProfilePicture = (string)jo.SelectToken("picture.data.url");</code>
自定义JSON转换器
为了获得更优雅的解决方案,可以创建一个自定义JsonConverter,使[JsonProperty]
属性能够按预期工作。此转换器在类级别运行,利用反射和上述技术来填充属性。
<code class="language-csharp">public class JsonPathConverter : JsonConverter { public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { JObject jo = JObject.Load(reader); object targetObj = Activator.CreateInstance(objectType); foreach (var prop in objectType.GetProperties() .Where(p => p.CanRead && p.CanWrite)) { var att = prop.GetCustomAttributes(true) .OfType<JsonPropertyAttribute>() .FirstOrDefault(); string jsonPath = (att != null ? att.PropertyName : prop.Name); JToken token = jo.SelectToken(jsonPath); if (token != null && token.Type != JTokenType.Null) { object value = token.ToObject(prop.PropertyType, serializer); prop.SetValue(targetObj, value, null); } } return targetObj; } }</code>
为了演示,考虑一个更复杂的JSON对象:
<code class="language-json">{ "name": "Joe Shmoe", "age": 26, "picture": { "id": 123456, "data": { "type": "jpg", "url": "http://www.someplace.com/mypicture.jpg" } }, "favorites": { "movie": { "title": "The Godfather", "starring": "Marlon Brando", "year": 1972 }, "color": "purple" } }</code>
在下面的目标类中,每个属性路径都使用[JsonProperty]
属性指定:
<code class="language-csharp">[JsonConverter(typeof(JsonPathConverter))] public class Person { [JsonProperty("name")] public string Name { get; set; } [JsonProperty("age")] public int Age { get; set; } [JsonProperty("picture.data.url")] public string ProfilePicture { get; set; } [JsonProperty("favorites.movie")] public Movie FavoriteMovie { get; set; } [JsonProperty("favorites.color")] public string FavoriteColor { get; set; } } public class Movie { public string Title { get; set; } public int Year { get; set; } }</code>
有了这些属性,反序列化应该可以无缝工作:
<code class="language-csharp">Person p = JsonConvert.DeserializeObject<Person>(json);</code>
以上是如何在 Newtonsoft.Json 反序列化中将子 JSON 属性映射到类属性?的详细内容。更多信息请关注PHP中文网其他相关文章!