在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中文網其他相關文章!