C # - анализ данных, отформатированных в json, во вложенные хеш-таблицы - PullRequest
4 голосов
/ 29 апреля 2009

Я пытаюсь работать с некоторыми данными, отформатированными в json, в C #, но у меня возникают некоторые проблемы с определением правильного способа решения этой проблемы. Моя проблема в том, что данные в формате 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 #, который позволил бы мне легко разобрать это во вложенный набор hastables?

Я хотел бы сделать что-то вроде (обратите внимание, что этот код синтаксически не на 100% корректен, и его лучше сделать с помощью рекурсии ... но идея понятна).

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

Ответы [ 4 ]

4 голосов
/ 29 апреля 2009

В .NET у вас есть JsonArray , который позволяет загружать и анализировать данные JSON. Он создает массив JsonValue и полностью вложен на основе данных JSON, которые он анализирует.

Если вам конкретно нужен Hashtable, вы можете перевести данные из JsonArray, хотя Hastable почти устарел в пользу словаря.

У Джоша Холмса есть довольно хорошая статья о начале работы с JSON в .NET: http://www.joshholmes.com/blog/2009/01/20/PlayingWithJSON.aspx

3 голосов
/ 29 апреля 2009

Мне не понравился разбор .Net Json ... иногда он делает странные вещи. Я перешел на Json.NET , библиотеку с открытым исходным кодом. У него есть хороший объект JObject, который будет делать то, что вам нужно.

2 голосов
/ 15 июня 2011

Возможно, вы захотите взглянуть на http://techblog.procurios.nl/k/n618/news/view/14605/14863/How-do-I-write-my-own-parser-for-JSON.html Это простая библиотека, которая анализирует строку JSON в Hashtables и ArrayLists. Он также может снова превратить эти структуры в JSON.

0 голосов
/ 15 августа 2012

Вот метод, который я написал в 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;
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...