DeserializeObject<T>(strJSONData)
“raw_property_name”)]`可以将原始JSON数据映射到类中的正确属性。有没有一种方法可以将JSON复杂对象的child属性映射到简单属性?这是一个例子:
{ "picture": { "id": 123456, "data": { "type": "jpg", "url": "http://www.someplace.com/mypicture.jpg" } } }
除了URL,我不在乎图片对象的其余部分,因此也不想在我的C#类中设置复杂的对象。我真的只想要这样的东西:
[DataMember(Name = "picture.data.url")] public string ProfilePicture { get; set; }
这可能吗?
好吧,如果您只需要一个额外的属性,一种简单的方法是将JSON解析为JObject,使用ToObject()从中填充类JObject,然后再使用SelectToken()来引入额外的属性。
JObject
ToObject()
SelectToken()
因此,假设您的课程如下所示:
class Person { [JsonProperty("name")] public string Name { get; set; } [JsonProperty("age")] public string Age { get; set; } public string ProfilePicture { get; set; } }
您可以这样做:
string json = @" { ""name"" : ""Joe Shmoe"", ""age"" : 26, ""picture"": { ""id"": 123456, ""data"": { ""type"": ""jpg"", ""url"": ""http://www.someplace.com/mypicture.jpg"" } } }"; JObject jo = JObject.Parse(json); Person p = jo.ToObject<Person>(); p.ProfilePicture = (string)jo.SelectToken("picture.data.url");
小提琴:https : //dotnetfiddle.net/7gnJCK
如果您希望使用更高级的解决方案,则可以进行自定义,JsonConverter以使JsonProperty属性表现出您所描述的行为。转换器将需要在类级别上运行,并结合使用上述技术和某些技术来填充所有属性。这是代码中的样子:
JsonConverter
JsonProperty
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 (PropertyInfo prop in objectType.GetProperties() .Where(p => p.CanRead && p.CanWrite)) { JsonPropertyAttribute 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; } public override bool CanConvert(Type objectType) { // CanConvert is not called when [JsonConverter] attribute is used return false; } public override bool CanWrite { get { return false; } } public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { throw new NotImplementedException(); } }
为了演示,我们假设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" } }
…除了您之前的信息外,您还对该人最喜欢的电影(标题和年份)和最喜欢的颜色感兴趣。您将首先用[JsonConverter]属性标记目标类,以将其与定制转换器关联,然后[JsonProperty]在每个属性上使用属性,并指定所需的属性路径(区分大小写)作为名称。目标属性也不必是原语- 您可以像我在此处使用的那样使用子类Movie(请注意,不需要中间Favorites类)。
[JsonConverter]
[JsonProperty]
Movie
Favorites
[JsonConverter(typeof(JsonPathConverter))] 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; } } // Don't need to mark up these properties because they are covered by the // property paths in the Person class class Movie { public string Title { get; set; } public int Year { get; set; } }
有了所有属性,您就可以照常反序列化了,它应该“正常工作”:
Person p = JsonConvert.DeserializeObject<Person>(json);
小提琴:https://dotnetfiddle.net/Ljw32O