C# - 将 json 格式的数据解析为嵌套的哈希表
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/802766/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
C# - parsing json formatted data into nested hashtables
提问by
I'm trying to work with some json formatted data in C#, but, I'm having some problems determining the proper way to approach the problem. My issue is that the json formatted data will be in an unknown format (I know that sounds odd … please read on). Basically, the json formatted data will be some collection of name/value pairs where the values may or may not be arrays of nested name/value pairs. To make things more fun, the nesting of the name/value pair arrays can continue on ad infinitum.
我正在尝试在 C# 中处理一些 json 格式的数据,但是,我在确定解决问题的正确方法时遇到了一些问题。我的问题是 json 格式的数据将采用未知格式(我知道这听起来很奇怪……请继续阅读)。基本上,json 格式的数据将是一些名称/值对的集合,其中值可能是也可能不是嵌套名称/值对的数组。为了让事情变得更有趣,名称/值对数组的嵌套可以无限地继续。
For example: I might have some data that looks like…
例如:我可能有一些数据看起来像……
{
"1": {
"1.1": {
"1.1.1": "value1",
"1.1.2": "value2",
"1.1.3": "value3"
},
"1.2": "value4",
"1.3": {
"1.3.1": {
"1.3.1.1": "value5",
"1.3.1.2": "value6"
},
"1.3.1.2": "value7",
"1.3.1.3": "value8"
}
}
}
Unfortunately, I don't know how much nesting is going to occur and technically I don't know what names/value pairs will be present in any given message.
不幸的是,我不知道会发生多少嵌套,而且从技术上讲,我不知道任何给定消息中将出现哪些名称/值对。
Is there any supported mechanism in C# that would enable me to easily parse this into a nested set of hastables?
C# 中是否有任何受支持的机制可以让我轻松地将其解析为一组嵌套的 hastables?
I'd like to do something along the lines of (note this code is not 100% syntactically correct and would better be done via recursion … but it get's the idea across).
我想做一些类似的事情(请注意,这段代码在语法上不是 100% 正确的,最好通过递归来完成……但它使这个想法变得清晰)。
Hashtable ht = [deserialize data method](jsonformattedstring);
foreach (Hashtable nested in ht)
{
If (nested.count > 1)
{
Foreach (hashtable next in nested)
…
}
}
采纳答案by jvenema
回答by Brian Genisio
In .NET, you have the JsonArray, which allows you to load up and parse the JSON data. It creates an array of JsonValue and it is completely nested based on the JSON data it parses.
在 .NET 中,您有JsonArray,它允许您加载和解析 JSON 数据。它创建了一个 JsonValue 数组,它是基于它解析的 JSON 数据完全嵌套的。
If you specifically need Hashtable, you could translate the data from JsonArray, though Hastable is all but deprecated in favor of Dictionary.
如果您特别需要 Hashtable,您可以从 JsonArray 翻译数据,尽管 Hastable 几乎已被弃用而支持 Dictionary。
Josh Holmes has a pretty good "getting started" post about JSON in .NET: http://www.joshholmes.com/blog/2009/01/20/PlayingWithJSON.aspx
Josh Holmes 有一篇关于 .NET 中 JSON 的非常好的“入门”帖子:http: //www.joshholmes.com/blog/2009/01/20/PlayingWithJSON.aspx
回答by Patrick van Bergen
You may want to look at http://techblog.procurios.nl/k/n618/news/view/14605/14863/How-do-I-write-my-own-parser-for-JSON.htmlIt is a simple library that parses a JSON string into Hashtables and ArrayLists. It can also turn these structures into JSON again.
你可能想看看http://techblog.procurios.nl/k/n618/news/view/14605/14863/How-do-I-write-my-own-parser-for-JSON.html这是一个将 JSON 字符串解析为 Hashtables 和 ArrayLists 的简单库。它还可以将这些结构再次转换为 JSON。
回答by Sam Grondahl
Here is a method I wrote in C# to parse JSON and return a dictionary. Of course it is not appropriate for all use cases, but something like this will give you a nice one-pass parse of the JSON:
这是我用 C# 编写的一个方法来解析 JSON 并返回一个字典。当然,它并不适用于所有用例,但这样的事情会给你一个很好的 JSON 一次性解析:
/*
* This method takes in JSON in the form returned by javascript's
* JSON.stringify(Object) and returns a string->string dictionary.
* This method may be of use when the format of the json is unknown.
* You can modify the delimiters, etc pretty easily in the source
* (sorry I didn't abstract it--I have a very specific use).
*/
public static Dictionary<string, string> jsonParse(string rawjson)
{
Dictionary<string, string> outdict = new Dictionary<string, string>();
StringBuilder keybufferbuilder = new StringBuilder();
StringBuilder valuebufferbuilder = new StringBuilder();
StringReader bufferreader = new StringReader(rawjson);
int s = 0;
bool reading = false;
bool inside_string = false;
bool reading_value = false;
//break at end (returns -1)
while (s >= 0)
{
s = bufferreader.Read();
//opening of json
if (!reading)
{
if ((char)s == '{' && !inside_string && !reading) reading = true;
continue;
}
else
{
//if we find a quote and we are not yet inside a string, advance and get inside
if (!inside_string)
{
//read past the quote
if ((char)s == '\"') inside_string = true;
continue;
}
if (inside_string)
{
//if we reached the end of the string
if ((char)s == '\"')
{
inside_string = false;
s = bufferreader.Read(); //advance pointer
if ((char)s == ':')
{
reading_value = true;
continue;
}
if (reading_value && (char)s == ',')
{
//we know we just ended the line, so put itin our dictionary
if (!outdict.ContainsKey(keybufferbuilder.ToString())) outdict.Add(keybufferbuilder.ToString(), valuebufferbuilder.ToString());
//and clear the buffers
keybufferbuilder.Clear();
valuebufferbuilder.Clear();
reading_value = false;
}
if (reading_value && (char)s == '}')
{
//we know we just ended the line, so put itin our dictionary
if (!outdict.ContainsKey(keybufferbuilder.ToString())) outdict.Add(keybufferbuilder.ToString(), valuebufferbuilder.ToString());
//and clear the buffers
keybufferbuilder.Clear();
valuebufferbuilder.Clear();
reading_value = false;
reading = false;
break;
}
}
else
{
if (reading_value)
{
valuebufferbuilder.Append((char)s);
continue;
}
else
{
keybufferbuilder.Append((char)s);
continue;
}
}
}
else
{
switch ((char)s)
{
case ':':
reading_value = true;
break;
default:
if (reading_value)
{
valuebufferbuilder.Append((char)s);
}
else
{
keybufferbuilder.Append((char)s);
}
break;
}
}
}
}
return outdict;
}