使用动态键反序列化 JSON

Posted

技术标签:

【中文标题】使用动态键反序列化 JSON【英文标题】:Deserializing JSON with dynamic keys 【发布时间】:2012-11-11 03:39:07 【问题描述】:

我对 JSON 很陌生,目前正在学习(反)序列化。 我正在从网页中检索 JSON 字符串并尝试将其反序列化为对象。问题是,根 json 键是静态的,但底层键是动态的,我无法预料它们会反序列化。这是字符串的一个小例子:


    "daily": 
        "1337990400000": 443447,
        "1338076800000": 444693,
        "1338163200000": 452282,
        "1338249600000": 462189,
        "1338336000000": 466626
    

对于我的应用程序中的另一个 JSON 字符串,我使用了 javascriptSerializer 并使用类结构预测密钥。将此字符串反序列化为对象的最佳方法是什么?

【问题讨论】:

“期待”一个字典怎么样? 如果您可以发布一个示例作为答案,那就太好了:) 我已经编辑了你的标题。请参阅“Should questions include “tags” in their titles?”,其中的共识是“不,他们不应该”。 【参考方案1】:

说真的,没必要走动态路线;使用

var deser = new JavaScriptSerializer()
    .Deserialize<Dictionary<string, Dictionary<string, int>>>(val);
var justDaily = deser["daily"];

获取字典,然后你可以例如

foreach (string key in justDaily.Keys)
    Console.WriteLine(key + ": " + justDaily[key]);

获取存在的键和对应的值。

【讨论】:

工作就像一个绝对的魅力:) 谢谢!这似乎是我收到的所有答案中最合乎逻辑的路线。 附言。您忘记了 Dictionary 调用中的第三个右 > 括号! @JasonHiggins 谢谢。【参考方案2】:

您可以在 .NET 4 或更高版本中使用 dynamic。例如,我可以使用 JSON.NET:

dynamic obj = JsonConvert.Deserialize<dynamic>("x: 'hello'");

你可以这样做:

var str = obj.x;

但是,不确定它将如何处理数字键。你当然可以直接使用JObject 本身,例如:

var obj = JObject.Parse("'123456': 'help'");
var str = obj["123456"];

【讨论】:

如果他不知道键是什么,你能从动态中得到一个“所有键”集合吗? 可能使用反射是的(不会很漂亮)。我更喜欢使用 JObject,因为它基本上会收缩包装各种字典。【参考方案3】:

只要您有带有动态键的 JSON,它通常可以反序列化为 Dictionary&lt;string, SomeObject&gt;。由于内部 JSON 键是动态的(在这个问题中),因此 JSON 可以建模为:

Dictionary<string, Dictionary<string, int>>

我建议使用 NewtonSoft.Json (JSON.Net) 或 System.Text.Json(如果您使用 .NET-Core 3.0 及更高版本)。

Newtonsoft.Json

使用来自JsonConvertDeserializeObject&lt;T&gt;

var response = JsonConvert.DeserializeObject<Dictionary<string, Dictionary<string, int>>>(json);

System.Text.Json

使用来自JsonSerializerDeserialize&lt;T&gt;

var response = JsonSerializer.Deserialize<Dictionary<string, Dictionary<string, int>>>(json);

【讨论】:

【参考方案4】:

这使用起来不方便,因为在с#中不能定义一个以数字开头的变量。为键添加前缀。

或者试试这个:

string json = "
 daily:[
   key: '1337990400000', val:443447 ,
   key: '1338076800000', val:444693 ,
   key: '1338163200000', val:452282 ,
   key: '1338249600000', val:462189 ,
   key: '1338336000000', val:466626 ]
";

public class itemClass

  public string key; // or int
  public int val;


public class items

  public itemClass[] daily;


items daily = (new JavascriptSerializer()).Deserialize<items>(json);

那么你可以:

var itemValue = items.Where(x=>x.key=='1338163200000').Select(x=>x.val).FirstOrDefault();

【讨论】:

没有理由更改 JSON。 C# 可以愉快地处理以数字开头的字典键。 最重要的是这不是带有动态键的 JSON

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

C#动态实体集的反序列化(动态JSON反序列化)

使用 System.Text.Json 使用动态键查询或反序列化 json

无法使用泛型使用 Jackson 反序列化动态 json

Newtonsoft.Json.JsonSerializationException:'反序列化对象时出现意外标记:使用动态对象注释

使用 Json.net 将 JSON 对象反序列化为动态对象

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