使用带有JSON.Net的自定义反序列化器反序列化JSON

时间:2013-10-17 16:28:01

标签: c# json json.net deserialization

我的JSON看起来像这样:

{
  "MobileSiteContents": {
    "au/en": [
      "http://www.url1.com",
      "http://www.url2.com",

    ],
    "cn/zh": [
      "http://www.url2643.com",

    ]
  }
}

我正在尝试将其反序列化为IEnumerable类,如下所示:

public class MobileSiteContentsContentSectionItem : ContentSectionItem
{
    public string[] Urls { get; set; }
}

public abstract class ContentSectionItem
{
    public string Culture { get; set; }
}

这可能吗?
我意识到我可能需要使用自定义JsonConverter,但找不到任何示例。

我开始编写一种使用JObject.Parse进行转换的方法,但不确定这是否是正确/最有效的路线:

public IEnumerable<MobileSiteContentsContentSectionItem> Parse(string json)
{
    var jobject = JObject.Parse(json);

    var result = new List<MobileSiteContentsContentSectionItem>();

    foreach (var item in jobject.Children())
    {
        var culture = item.Path;
        string[] urls = new[] { "" }; //= this is the part I'm having troble with here...

        result.Add(new MobileSiteContentsContentSectionItem { Culture = culture, Urls = urls });
    }

    return result;
}

2 个答案:

答案 0 :(得分:6)

你走在正确的轨道上。以下是您需要进行的更正:

  1. 您正在迭代顶级对象的子级,期望将实际位于对象中的数据进一步降低一级。您需要导航到MobileSiteContents属性的并迭代其中的子项。
  2. 当您使用Children()的{​​{1}}时,请使用允许您将其转换为JObject个对象的重载;这将使您更容易提取所需的数据。
  3. JProperty
  4. culture获取Name
  5. 要获取JProperty,请获取urls项的Value并使用JProperty将其转换为字符串数组。
  6. 以下是更正后的代码:

    ToObject<string[]>()

    如果您喜欢简洁的代码,可以将其缩减为“单行”:

    public IEnumerable<MobileSiteContentsContentSectionItem> Parse(string json)
    {
        var jObject = JObject.Parse(json);
    
        var result = new List<MobileSiteContentsContentSectionItem>();
    
        foreach (var item in jObject["MobileSiteContents"].Children<JProperty>())
        {
            var culture = item.Name;
            string[] urls = item.Value.ToObject<string[]>();
    
            result.Add(new MobileSiteContentsContentSectionItem { Culture = culture, Urls = urls });
        }
    
        return result;
    }
    

    演示:

    public IEnumerable<MobileSiteContentsContentSectionItem> Parse(string json)
    {
        return JObject.Parse(json)["MobileSiteContents"]
            .Children<JProperty>()
            .Select(prop => new MobileSiteContentsContentSectionItem
            {
                Culture = prop.Name,
                Urls = prop.Value.ToObject<string[]>()
            })
            .ToList();
    }
    

    输出:

    class Program
    {
        static void Main(string[] args)
        {
            string json = @"
            {
                ""MobileSiteContents"": {
                    ""au/en"": [
                        ""http://www.url1.com"",
                        ""http://www.url2.com"",
                    ],
                    ""cn/zh"": [
                        ""http://www.url2643.com"",
                    ]
                }
            }";
    
            foreach (MobileSiteContentsContentSectionItem item in Parse(json))
            {
                Console.WriteLine(item.Culture);
                foreach (string url in item.Urls)
                {
                    Console.WriteLine("  " + url);
                }
            }
        }
    
        public static IEnumerable<MobileSiteContentsContentSectionItem> Parse(string json)
        {
            return JObject.Parse(json)["MobileSiteContents"]
                .Children<JProperty>()
                .Select(prop => new MobileSiteContentsContentSectionItem()
                {
                    Culture = prop.Name,
                    Urls = prop.Value.ToObject<string[]>()
                })
                .ToList();
        }
    
        public class MobileSiteContentsContentSectionItem : ContentSectionItem
        {
            public string[] Urls { get; set; }
        }
    
        public abstract class ContentSectionItem
        {
            public string Culture { get; set; }
        }
    }
    

答案 1 :(得分:3)

我使用Json.Net尝试了这个并且运行正常。

public IEnumerable<MobileSiteContentsContentSectionItem> Parse(string json)
{
     dynamic jobject = Newtonsoft.Json.JsonConvert.DeserializeObject(json);

     var result = new List<MobileSiteContentsContentSectionItem>();

     var urls = new List<string>();
     foreach (var item in jobject.MobileSiteContents)
     {
         var culture = item.Name;
         foreach(var url in item.Value)
            urls.Add(url.Value);

         result.Add(new MobileSiteContentsContentSectionItem { Culture = culture, Urls = urls.ToArray() });
     }

     return result;
}