Question

J'essaie de travailler avec des données au format json en C #, mais je ne parviens pas à trouver la bonne façon de résoudre le problème. Mon problème est que les données au format JSON seront dans un format inconnu (je sais que cela semble étrange… s'il vous plaît lisez la suite). Fondamentalement, les données au format json seront une collection de paires nom / valeur où les valeurs peuvent ou non être des tableaux de paires nom / valeur imbriquées. Pour rendre les choses plus amusantes, l’imbrication des tableaux de paires nom / valeur peut se poursuivre à l’infini.

Par exemple:     J'ai peut-être des données qui ressemblent à…

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

Malheureusement, je ne sais pas combien de temps l’imbrication va se produire ni, techniquement, je ne sais pas quelles paires nom / valeur seront présentes dans un message donné.

Existe-t-il un mécanisme pris en charge en C # qui me permettrait de facilement analyser cela dans un ensemble imbriqué de hastables?

J'aimerais faire quelque chose dans le sens de (notez que ce code n'est pas syntaxiquement correct à 100% et qu'il serait préférable de le faire via la récursivité ...

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

La solution

Je n’ai pas aimé l’analyse .Net Json ... elle fait parfois des choses étranges. Je suis passé à Json.NET , une bibliothèque à code source ouvert. Il a un bel objet JObject qui fera ce dont vous avez besoin.

Autres conseils

Dans .NET, vous avez le JsonArray , qui vous permet de charger et d’analyser les données JSON. Il crée un tableau de JsonValue et il est complètement imbriqué en fonction des données JSON analysées.

Si vous avez spécifiquement besoin de Hashtable, vous pouvez traduire les données de JsonArray, bien que Hastable soit à peu près obsolète en faveur de Dictionary.

Josh Holmes a un très bon "commencer" " poste sur JSON dans .NET: http://www.joshholmes.com/blog/2009/01/ 20 / PlayingWithJSON.aspx

Vous voudrez peut-être consulter http://techblog.procurios.nl/k/n618/news/view/14605/14863/How-do-I-write-my-own-parser-for- JSON.html C'est une bibliothèque simple qui analyse une chaîne JSON dans Hashtables et ArrayLists. Il peut également transformer à nouveau ces structures en JSON.

Voici une méthode que j'ai écrite en C # pour analyser JSON et renvoyer un dictionnaire. Bien sûr, cela ne convient pas à tous les cas d'utilisation, mais vous obtiendrez une analyse en une passe du code 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;
    }
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top