Pregunta

Estoy tratando de trabajar con algunos datos con formato json en C #, pero tengo algunos problemas para determinar la forma correcta de abordar el problema. Mi problema es que los datos con formato json estarán en un formato desconocido (sé que suena extraño & # 8230; sigue leyendo). Básicamente, los datos con formato json serán una recopilación de pares de nombre / valor donde los valores pueden o no ser matrices de pares de nombre / valor anidados. Para hacer las cosas más divertidas, el agrupamiento de las matrices de pares nombre / valor puede continuar hasta el infinito.

Por ejemplo:     Es posible que tenga algunos datos que parecen & # 8230;

{
    "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"
        }
    }
}

Desafortunadamente, no sé cuánto anidar se producirá y técnicamente no sé qué pares de nombre / valor estarán presentes en cualquier mensaje.

¿Existe algún mecanismo admitido en C # que me permita analizarlo fácilmente en un conjunto anidado de variables?

Me gustaría hacer algo en la línea de (tenga en cuenta que este código no es 100% sintácticamente correcto y sería mejor hacerlo a través de la recursión & # 8230; pero la idea es clara).

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

Solución

No me gustó el análisis de .Net Json ... hace algunas cosas extrañas de vez en cuando. Me cambié a Json.NET , una biblioteca de código abierto. Tiene un bonito objeto JObject que hará lo que necesites.

Otros consejos

En .NET, tiene la JsonArray , que te permite cargar y analizar los datos JSON. Crea una matriz de JsonValue y está completamente anidada en función de los datos JSON que analiza.

Si necesita Hashtable específicamente, puede traducir los datos de JsonArray, aunque Hastable está casi en desuso en favor del Diccionario.

Josh Holmes tiene un muy buen " inicio " post sobre JSON en .NET: http://www.joshholmes.com/blog/2009/01/ 20 / PlayingWithJSON.aspx

Es posible que desee ver http://techblog.procurios.nl/k/n618/news/view/14605/14863/How-do-I-write-my-own-parser-for- JSON.html Es una biblioteca simple que analiza una cadena JSON en Hashtables y ArrayLists. También puede convertir estas estructuras en JSON nuevamente.

Aquí hay un método que escribí en C # para analizar JSON y devolver un diccionario. Por supuesto, no es apropiado para todos los casos de uso, pero algo como esto le dará un buen análisis de una sola pasada del 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;
    }
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top