使用具有 JSON.Net 的自定义反序列化程序反序列化 JSON

本文关键字:反序列化 JSON 自定义 程序 Net | 更新日期: 2023-09-27 18:35:52

我有看起来像这样的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;
}

使用具有 JSON.Net 的自定义反序列化程序反序列化 JSON

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

  1. 您正在迭代顶级对象的子对象,期望获取实际位于更下一级的对象中的数据。 您需要导航到 MobileSiteContents 属性的值并循环访问该属性的子属性。
  2. 当你Children() JObject时,使用重载,让你把它们投射到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

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