使用 JSON.NET 反序列化任何内容

Posted

技术标签:

【中文标题】使用 JSON.NET 反序列化任何内容【英文标题】:Deserializing anything using JSON.NET 【发布时间】:2017-02-19 02:48:05 【问题描述】:

我将 JSON 反序列化为已知类型或 Dictionary 对象没有问题,但是如果我不知道输入将是什么情况呢?具体来说,我指的是接收代表一组平面或嵌套键值对的 JSON 字符串:

 
  foo: 'bar',
  baz: 42


  foo: 
  
    bar: 42,
    baz: ['foo', 'bar', 'baz']
  

但是如果输入不是键值对,而是一个数组,或者一个包含其他嵌套对象(包括数组)的对象数组,该怎么办?

[
   foo: 'bar', baz: [ 1, 2, 3 ] ,
   foo: 'baz', bar: [ 4, 5, 6 ] 
]

我的目标是拥有一个可以反序列化上述任何内容的类,然后迭代它的每个成员。输入可以是任何结构,所以我不能假设数据会匹配我已经定义的任何类型。

我还没有找到方法来做到这一点。有人有什么指导吗?

编辑:

JToken 似乎很容易。解析 JSON 字符串;一个有用的下一步是迭代其成员并分别处理 JArray 和 JObject。

【问题讨论】:

您是否考虑过反序列化为动态? ***.com/questions/4535840/… 是的,当输入是一个没有键的数组时,我似乎无法让它工作。 没有键的数组是什么意思? 您所描述的是LINQ-to-JSON API (JTokens)。使用JToken token = JToken.Parse(json)。或者,如果您更喜欢普通的旧 .Net 对象,请参阅 How do I use JSON.NET to deserialize into nested/recursive Dictionary and List? @joelc 我添加了一个答案,展示了如何迭代 JToken 的成员。 【参考方案1】:

您所描述的内容已经存在于 Json.Net 中——它是 LINQ-to-JSON API (JTokens)。下面是一个使用它来解析任意 JSON 并遍历成员的示例。请注意,您需要一个递归方法来执行此操作,因为 JSON 可以嵌套到任何深度。

using Newtonsoft.Json.Linq;
public class Program

    public static void Main(string[] args)
    
        string json1 = @"
        
          ""foo"":  ""bar"": 42, ""baz"": [ ""a"", ""b"", ""c"" ] 
        ";
        DeserializeAndDump(json1, "example 1");

        string json2 = @"
        [
           ""foo"": ""bar"", ""baz"": [ 1, 2, 3 ] ,
           ""foo"": ""baz"", ""bar"": [ 4, 5, 6 ] 
        ]";
        DeserializeAndDump(json2, "example 2");
    

    public static void DeserializeAndDump(string json, string label)
    
        Console.WriteLine("---- " + label + " ----");
        JToken token = JToken.Parse(json);
        DumpJToken(token);
        Console.WriteLine();
    

    public static void DumpJToken(JToken token, string indent = "")
    
        if (token.Type == JTokenType.Object)
        
            Console.WriteLine(indent + "begin object");
            foreach (JProperty prop in token.Children<JProperty>())
            
                Console.WriteLine(indent + "  " + prop.Name + ":");
                DumpJToken(prop.Value, indent + "    ");
            
            Console.WriteLine(indent + "end object");
        
        else if (token.Type == JTokenType.Array)
        
            Console.WriteLine(indent + "begin array");
            foreach (JToken child in token.Children())
            
                DumpJToken(child, indent + "  ");
            
            Console.WriteLine(indent + "end array");
        
        else
        
            Console.WriteLine(indent + token.ToString() + " (" + token.Type.ToString() + ")");
        
    

这是上面的输出:

---- example 1 ----
begin object
  foo:
    begin object
      bar:
        42 (Integer)
      baz:
        begin array
          a (String)
          b (String)
          c (String)
        end array
    end object
end object

---- example 2 ----
begin array
  begin object
    foo:
      bar (String)
    baz:
      begin array
        1 (Integer)
        2 (Integer)
        3 (Integer)
      end array
  end object
  begin object
    foo:
      baz (String)
    bar:
      begin array
        4 (Integer)
        5 (Integer)
        6 (Integer)
      end array
  end object
end array

小提琴:https://dotnetfiddle.net/dfk0sj

【讨论】:

Brian 非常感谢您提供的完美示例。我非常感谢您花时间做这件事。 没问题;很高兴我能帮上忙。

以上是关于使用 JSON.NET 反序列化任何内容的主要内容,如果未能解决你的问题,请参考以下文章

csharp 使用Newtonsoft JSON.NET将任何对象序列化/反序列化为JSON

Json 反序列化 C#

使用Newtonsoft.Json.dll(JSON.NET)动态解析JSON.net 的json的序列化与反序列化

Json.net反序列化不反序列化所有属性

使用 json.net 反序列化没有类型信息的多态 json 类

使用 Json.NET 自定义反序列化