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

6

我有一个长这样的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个回答

6
你已经走在了正确的轨道上,以下是你需要进行的更正:
  1. 你正在遍历顶层对象的子项,期望获取实际位于下一级对象中的数据。你需要导航到“MobileSiteContents”属性的“value”,并遍历该属性的子项。
  2. 当你获取“JObject”的“Children()”时,请使用可以将它们转换为“JProperty”对象的重载;这将使提取所需数据变得更加容易。
  3. 从“JProperty”项的“Name”中获取“culture”。
  4. 要获取“urls”,请获取“JProperty”项的“Value”,并使用“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; }
    }
}

输出:

au/en
  http://www.url1.com
  http://www.url2.com
cn/zh
  http://www.url2643.com

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;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接