Ответ 1
Мне не нравился синтаксический анализ .Net Json... это иногда случается с некоторыми странными вещами. Я перешел на Json.NET - библиотеку с открытым исходным кодом. Он имеет хороший объект JObject, который будет делать то, что вам нужно.
Я пытаюсь работать с некоторыми форматированными 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"
}
}
}
К сожалению, я не знаю, сколько будет гнездования, и технически я не знаю, какие пары имя/значение будут присутствовать в любом сообщении.
Есть ли какой-либо поддерживаемый механизм в С#, который позволил бы мне легко разобрать его во вложенный набор hastables?
Мне нравится делать что-то по строкам (обратите внимание, что этот код не является на 100% синтаксически правильным и лучше делать через рекурсию... но он переводит идею).
Hashtable ht = [deserialize data method](jsonformattedstring);
foreach (Hashtable nested in ht)
{
If (nested.count > 1)
{
Foreach (hashtable next in nested)
…
}
}
Мне не нравился синтаксический анализ .Net Json... это иногда случается с некоторыми странными вещами. Я перешел на Json.NET - библиотеку с открытым исходным кодом. Он имеет хороший объект JObject, который будет делать то, что вам нужно.
В .NET у вас есть JsonArray, который позволяет загружать и анализировать данные JSON. Он создает массив JsonValue и полностью вложен на основе данных JSON, которые он анализирует.
Если вам нужна Hashtable, вы можете перевести данные из JsonArray, хотя Hastable почти устарел в пользу словаря.
Джош Холмс имеет неплохую статью о том, как начать работу над JSON в .NET: http://www.joshholmes.com/blog/2009/01/20/PlayingWithJSON.aspx
Вы можете посмотреть http://techblog.procurios.nl/k/n618/news/view/14605/14863/How-do-I-write-my-own-parser-for-JSON.html Это простая библиотека, которая анализирует строку JSON в Hashtables и ArrayLists. Он также может снова превратить эти структуры в JSON.
Вот метод, который я написал в С# для разбора 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;
}