使用动态键反序列化JSON

17

我对JSON还比较陌生,目前正在学习(反)序列化。 我从网页中检索到一个JSON字符串,并尝试将其反序列化为一个对象。问题是,根JSON键是静态的,但底层键是动态的,我无法预测它们进行反序列化。以下是该字符串的一个小例子:

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

在我的应用程序中,我使用了JavascriptSerializer并利用类结构对键进行预期。如何最好地将此字符串反序列化为对象?


1
期望一个 Dictionary<string,string> 怎么样? - Jorge Alvarado
如果您能将其作为答案发布一个示例,那就太好了 :) - Jason Higgins
2
我已经编辑了你的标题。请参考“问题的标题应该包含“标签”吗?”,在那里达成共识是“不应该”。 - John Saunders
4个回答

37

真的,没必要采取动态路线;使用

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]);

获取当前键和对应的值。


5
您可以在.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"];

如果他不知道键将是什么,你能否从动态获取“所有键”集合? - Rawling
可能会使用反射(不太美观)。 我更喜欢使用JObject,因为它基本上是一个类似字典的包装。 - Lloyd

5
每当您有动态键的JSON时,通常可以将其反序列化为Dictionary<string, SomeObject>。由于内部JSON键是动态的(在此问题中),因此可以将JSON建模为:
Dictionary<string, Dictionary<string, int>>

我建议使用NewtonSoft.Json(JSON.Net)或System.Text.Json(如果您正在使用.NET Core 3.0及以上版本)。

Newtonsoft.Json

使用 JsonConvert 中的 DeserializeObject<T> 方法:
var response = JsonConvert.DeserializeObject<Dictionary<string, Dictionary<string, int>>>(json);

System.Text.Json

使用JsonSerializer中的Deserialize<T>方法:
var response = JsonSerializer.Deserialize<Dictionary<string, Dictionary<string, int>>>(json);

-2

这种方式不太方便,因为在 C# 中不能定义以数字开头的变量。请给键添加前缀。

或者尝试这个:

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#可以轻松处理以数字开头的字典键。 - Rawling
最重要的是,这不是一个具有动态键的JSON。 - Sajeeb Chandan Saha

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