C# - 将JSON格式的数据解析为嵌套哈希表

6
我正在尝试在C#中处理一些json格式的数据,但是我遇到了一些问题,无法确定正确的解决方法。我的问题是,json格式的数据将以未知格式存在(我知道这听起来很奇怪...请继续阅读)。基本上,json格式的数据将是一些名称/值对的集合,其中值可能是嵌套名称/值对的数组,也可能不是。为了让事情更有趣,名称/值对数组的嵌套可以无限制地继续下去。
例如: 我可能有一些看起来像这样的数据...
{
    "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"
        }
    }
}

很不幸,我不知道会出现多少嵌套,从技术上讲,我也不知道在任何给定的消息中会有哪些名称/值对。

C#中是否有任何支持的机制可以使我轻松地将其解析为一组嵌套的哈希表?

我想做类似以下的事情(请注意,此代码不是100%语法正确的,并且最好通过递归来完成...但它可以传达思想)。

Hashtable ht = [deserialize data method](jsonformattedstring);
foreach (Hashtable nested in ht)
{
    If (nested.count > 1)
        {
        Foreach (hashtable next in nested)
        …
        }
}
4个回答

4
在.NET中,你可以使用JsonArray(链接)来加载和解析JSON数据。它创建了一个JsonValue数组,完全基于它所解析的JSON数据嵌套。如果你特别需要Hashtable,你可以从JsonArray中翻译数据,虽然Hashtable已被Dictionary取代。Josh Holmes在.NET中有一篇关于JSON的“入门”文章:http://www.joshholmes.com/blog/2009/01/20/PlayingWithJSON.aspx

3
我认为它只能在Silverlight中使用。 - Skuli

4

我不喜欢 .Net 的 Json 解析,有时候会出现一些奇怪的问题。我已经转向使用Json.NET这个开源库,它有一个很好的 JObject 对象,可以满足你的需求。


JSON.NET工作得非常好(经过花费大量时间研究其复杂性)。我唯一的批评是JObject、JValue和其他“低级”对象没有很好的文档说明。感谢你指引我正确的方向。 - Typhoid
1
我和Typhoid处于同样的困境。你有解决原问题的代码示例吗?显然,Typhoid已经解决了,但我还没有。 - Pat

2

这个原始的C#代码要比处理依赖关系或者操纵序列化类和晦涩难懂的运行时结构更加高效。如果你只是想遍历一个结构,而不需要类的行为,那么这无疑是最好的解决方案。 - Dean Radcliffe

1
这是我用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;
    }

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