2016-02-25 45 views
3

考虑下面的嵌套的JSON字符串平坦类:反序列化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: 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

非常感谢,你的代码不适合我。我已经修复了一些问题,并以这样一种方式实现,即它将遍历任意数量的节点。我已经上传了这个要点,如果你想看看最终版本:https://gist.github.com/lucd/cdd57a2602bd975ec0a6 – Lucian