2016-02-25 3 views
3

Учитывая следующую вложенная JSON строки:Deserialize вложенная JSON к плоскому класса с использованием Json.NET

string s = @" 
{ 
    ""id"": 10, 
    ""fields"":{ 
     ""issuetype"": { 
      ""name"": ""Name of the jira item"" 
     } 
    } 
}"; 

Как я могу десериализацию его к следующему "сплющенным" классу, используя JsonPropertyAttribute:

public class JiraIssue 
{ 
    [JsonProperty("id")] 
    public int Id { get; set; } 
    [JsonProperty("fields/issuetype/name")] 
    public string Type { get; set; } 
} 

Я пытаюсь указать правило «навигации» на основе / в качестве разделителя во имя свойства JSON.

В принципе, я хочу, чтобы указать, что JsonProperty("fields/issuetype/name") следует использовать, как правило, навигации к вложенной собственности fields.issuetype.name, что, очевидно, не работает:

var d = Newtonsoft.Json.JsonConvert.DeserializeObject<JiraIssue>(s); 
Console.WriteLine("Id:" + d.Id); 
Console.WriteLine("Type" + d.Type); 

, приведенный выше распознает только Id:

Id: 10 
Type: 

Что мне нужно реализовать, чтобы сообщить Json.NET использовать «/» в качестве пути навигации к желаемому вложенному свойству?

+0

Вы не можете использовать JsonProperty для specift навигации path.BTW почему бы вам просто передать простой объект? –

ответ

3

Это один из возможных способов -

internal class ConventionBasedConverter : JsonConverter 
{ 
    public override bool CanConvert(Type objectType) 
    { 
     return typeof(JiraIssue).IsAssignableFrom(objectType); 
    } 

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) 
    { 
     var daat = JObject.Load(reader); 
     var ret = new JiraIssue(); 

     foreach (var prop in ret.GetType().GetProperties(BindingFlags.Public | BindingFlags.DeclaredOnly | BindingFlags.Instance)) 
     { 
      var attr = prop.GetCustomAttributes(false).FirstOrDefault(); 
      if (attr != null) 
      { 
       var propName = ((JsonPropertyAttribute)attr).PropertyName; 
       if (!string.IsNullOrWhiteSpace(propName)) 
       { 
        var conventions = propName.Split('/'); 
        if (conventions.Length == 3) 
        { 
         ret.Type = (string)((JValue)daat[conventions[0]][conventions[1]][conventions[2]]).Value; 
        } 

        ret.Id = Convert.ToInt32(((JValue)daat[propName]).Value); 
       }       
      } 
     } 


     return ret; 
    } 

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) 
    { 

    } 
} 

var settings = new JsonSerializerSettings(); 
settings.Converters.Add(new ConventionBasedConverter()); 
var o = JsonConvert.DeserializeObject<JiraIssue>(s, settings); 
+1

Большое спасибо за это, ваш код не работал из коробки для меня. Я исправил пару проблем и сделал это таким образом, чтобы он пересекал любое количество узлов. Я загрузил этот gist, если вы хотите посмотреть окончательную версию: https://gist.github.com/lucd/cdd57a2602bd975ec0a6 – Lucian

Смежные вопросы