22

我正在使用 WCF 服务,该服务返回包装在“d”根元素中的 JSON 结果。JSON 响应如下所示:

{"d":[
  {
    "__type":"DiskSpaceInfo:#Diagnostics.Common",
    "AvailableSpace":38076567552,
    "Drive":"C:\\",
    "TotalSpace":134789197824
  },
  {
    "__type":"DiskSpaceInfo:#Diagnostics.Common",
    "AvailableSpace":166942183424,
    "Drive":"D:\\",
    "TotalSpace":185149157376
  }
]}

我不想使用动态类型,我有我想在反序列化时使用的类 Diagnostics.Common.DiskSpaceInfo。

我正在使用 Json.NET (Netwonsoft JSON)。

问题是如何告诉它忽略根元素(那个'd'元素)并解析里面的内容。

到目前为止,我最好的解决方案是使用匿名类型:

DiskSpaceInfo[] result = JsonConvert.DeserializeAnonymousType(json, new
    {
        d = new DiskSpaceInfo[0]
    }).d;

这实际上有效,但我不太喜欢它。还有其他方法吗?我想要的是这样的:

DiskSpaceInfo[] result = JsonConvert.Deserialize(json, skipRoot: true);

或类似的东西...

4

3 回答 3

20

如果您知道在这种情况下要搜索什么“d”是根节点,那么您可以执行以下操作。

JObject jo = JObject.Parse(json);
DiskSpaceInfo[] diskSpaceArray = jo.SelectToken("d", false).ToObject<DiskSpaceInfo[]>();

如果您只是想忽略您不知道的根类,那么您可以使用您可以使用的“@Giu Do”解决方案,test2.ToObject<DiskSpaceInfo[]>();而不是Console.Write(test2);

        JObject o = JObject.Parse(json);
        if (o != null)
        {
            var test = o.First;
            if (test != null)
            {
                var test2 = test.First;
                if (test2 != null)
                {
                    DiskSpaceInfo[] diskSpaceArray = test2.ToObject<DiskSpaceInfo[]>();
                }
            }
        }
于 2012-12-04T17:12:12.147 回答
2

继这里以前的答案之后,我想建议使用您自己的静态实用程序类。这是可重用的,并且可以让您获得您正在寻找的语法。

public static class JsonUtil
{
    public static T Deserialize<T>(string json, bool ignoreRoot) where T : class
    {
        return ignoreRoot 
            ? JObject.Parse(json)?.Properties()?.First()?.Value?.ToObject<T>()
            : JObject.Parse(json)?.ToObject<T>();
    }
}

你会像这样调用它:

var resultA = JsonUtil.Deserialize<DiskSpaceInfo[]>(json, ignoreRoot: true);

或者

var resultB = JsonUtil.Deserialize<DiskSpaceInfoRoot>(json, ignoreRoot: false);
于 2017-10-09T09:41:22.340 回答
1

通过 Newtonsoft,我想您使用的是JSon.net,这是我的解决方案,我使用了此框架中可用的 Linq to JSon:

using System;
using Newtonsoft.Json.Linq;

namespace JSonTest
{
    class Program
    {
        static void Main(string[] args)
        {
            string json = @"{""d"":[
  {
    ""__type"":""DiskSpaceInfo:#Diagnostics.Common"",
    ""AvailableSpace"":38076567552,
    ""Drive"":""C:\\"",
    ""TotalSpace"":134789197824
  },
  {
    ""__type"":""DiskSpaceInfo:#Diagnostics.Common"",
    ""AvailableSpace"":166942183424,
    ""Drive"":""D:\\"",
    ""TotalSpace"":185149157376
  }
]}";
        JObject o = JObject.Parse(json);

        if (o != null)
        {
            var test = o.First;

            if (test != null)
            {
                var test2 = test.First;
                if (test2 != null)
                {
                    Console.Write(test2);
                }
            }
        }

        Console.Read();

    }
}
}

我使用了属性First,因为你需要找到d之后的第一个节点,也就是你收到的json的第一个节点。

您只需要创建一个重现 Main 的函数,不要忘记检查对象是否不为 null 以避免NullReferenceException

于 2012-12-04T15:31:20.093 回答