Question

J'essaie d'analyser un tableau d'objets JSON dans un tableau de chaînes en C #. Je peux extraire le tableau de l'objet JSON, mais je ne peux pas scinder la chaîne de tableau en un tableau d'objets individuels.

Ce que j'ai est cette chaîne de test:

string json = "{items:[{id:0,name:\"Lorem Ipsum\"},{id:1,name" 
            + ":\"Lorem Ipsum\"},{id:2,name:\"Lorem Ipsum\"}]}";

Pour le moment, j'utilise les expressions régulières suivantes pour diviser les éléments en objets individuels. Pour l'instant, ce sont deux expressions régulières distinctes jusqu'à ce que je résolve le problème avec la deuxième:

Regex arrayFinder = new Regex(@"\{items:\[(?<items>[^\]]*)\]\}"
                                 , RegexOptions.ExplicitCapture);
Regex arrayParser = new Regex(@"((?<items>\{[^\}]\}),?)+"
                                 , RegexOptions.ExplicitCapture);

La regex arrayFinder fonctionne comme prévu mais, pour des raisons que je ne comprends pas, la regex arrayParser ne fonctionne pas du tout. Tout ce que je veux, c'est diviser les éléments individuels en leurs propres chaînes afin d'obtenir une liste comme celle-ci:

  

{id: 0, nom: "Lorem Ipsum"}}
   {id: 1, nom: "Lorem Ipsum"}
   {id: 2, nom: "Lorem Ipsum"}

Que cette liste soit un tableau string [] ou une collection Groupe ou Match n'a pas d'importance, mais je suis stumped comme à la façon de séparer les objets. En utilisant le arrayParser et la chaîne json déclarés ci-dessus, j'ai essayé ce code qui, je suppose, fonctionnerait sans succès:

string json = "{items:[{id:0,name:\"Lorem Ipsum\"},{id:1,name" 
            + ":\"Lorem Ipsum\"},{id:2,name:\"Lorem Ipsum\"}]}";

Regex arrayFinder = new Regex(@"\{items:\[(?<items>[^\]]*)\]\}"
                                 , RegexOptions.ExplicitCapture);
Regex arrayParser = new Regex(@"((?<items>\{[^\}]\}),?)+"
                                 , RegexOptions.ExplicitCapture);

string array = arrayFinder.Match(json).Groups["items"].Value;
// At this point the 'array' variable contains: 
// {id:0,name:"Lorem Ipsum"},{id:1,name:"Lorem Ipsum"},{id:2,name:"Lorem Ipsum"}

// I would have expected one of these 2 lines to return 
// the array of matches I'm looking for
CaptureCollection c = arrayParser.Match(array).Captures;
GroupCollection g = arrayParser.Match(array).Groups;

Quelqu'un peut-il voir ce que je fais mal? Je suis totalement coincé là-dessus.

Était-ce utile?

La solution

Les parenthèses équilibrées sont littéralement un exemple classique d'une langue qui ne peut pas être traitée avec des expressions régulières. JSON se compose essentiellement de parenthèses équilibrées et d’un ensemble d’autres éléments, les accolades étant remplacées par des parenthèses. Dans la hiérarchie des langages formels , JSON est un langage sans contexte. Les expressions régulières ne peuvent pas analyser les langues sans contexte.

Certains systèmes offrent des extensions aux expressions régulières qui gèrent en quelque sorte les expressions équilibrées. Cependant, ce sont tous des hacks laids, ils sont tous inutilisables, et ils sont tous finalement le mauvais outil pour le travail.

Dans un travail professionnel, vous utiliseriez presque toujours un analyseur JSON existant. Si vous voulez avoir le vôtre à des fins éducatives, je vous conseillerais de commencer par une simple grammaire arithmétique qui prend en charge + - * / (). (JSON a des règles d'échappement qui, bien que peu complexes, rendront votre première tentative plus difficile que nécessaire.) En gros, vous devrez:

  1. Décomposez la langue en un alphabet de symboles
  2. Écrivez une grammaire sans contexte en termes de symboles qui reconnaissent la langue
  3. Convertissez la grammaire en forme normale de Chomsky ou assez près pour rendre l’étape 5 facile
  4. Ecrivez un lexer qui convertit le texte brut en alphabet de saisie
  5. Ecrivez un analyseur récursif de descente qui prend la sortie de votre lexer, l’analyse et produit une sorte de sortie

Il s’agit d’une mission typique de troisième année en CS dans presque toutes les universités.

L'étape suivante consiste à déterminer la complexité d'une chaîne JSON pour déclencher un débordement de pile dans votre analyseur récursif. Ensuite, examinez les autres types d’analyseurs pouvant être écrits et vous comprendrez pourquoi ceux qui doivent analyser un langage sans contexte dans le monde réel utilisent un outil tel que yacc ou antlr au lieu d’écrire manuellement un analyseur.

Si vous avez davantage à apprendre que ce que vous recherchiez, n'hésitez pas à utiliser un analyseur JSON standard, convaincu que vous avez appris quelque chose d'important et d'utile: les limites des expressions régulières.

Autres conseils

  

Les parenthèses équilibrées sont littéralement un exemple classique d'une langue qui ne peut pas être traitée avec des expressions régulières

bla bla bla ... vérifier ceci:

arrayParser = "(?<Key>[\w]+)":"?(?<Value>([\s\w\d\.\\\-/:_]+(,[,\s\w\d\.\\\-/:_]+)?)+)"?

cela fonctionne pour moi

si vous voulez faire correspondre les valeurs vides, changez le dernier '+' en '*'

Utilisez-vous .NET 3.5? Si tel est le cas, vous pouvez utiliser le DataContractJsonSerializer pour l’analyser. Il n'y a aucune raison de le faire vous-même.

Si vous n'utilisez pas .NET 3.5, vous pouvez utiliser Jayrock .

public Dictionary<string, string> ParseJSON(string s)
{
    Regex r = new Regex("\"(?<Key>[\\w]*)\":\"?(?<Value>([\\s\\w\\d\\.\\\\\\-/:_\\+]+(,[,\\s\\w\\d\\.\\\\\\-/:_\\+]*)?)*)\"?");
    MatchCollection mc = r.Matches(s);

    Dictionary<string, string> json = new Dictionary<string, string>();

    foreach (Match k in mc)
    {
        json.Add(k.Groups["Key"].Value, k.Groups["Value"].Value);

    }
    return json;
}

Cette fonction implémente l'expression régulière de Lukasz. J'ajoute seulement pour inclure + caractère au groupe de valeur (parce que je l'utilise pour analyser le jeton d'authentification de connexion en direct)

JSON ne peut généralement pas être analysé avec des expressions régulières (certaines variantes extrêmement simplifiées du JSON peuvent, mais elles ne sont pas JSON, mais autre chose).

Vous avez besoin d'un analyseur syntaxique pour analyser correctement JSON.

Et enfin, pourquoi essayez-vous d'analyser JSON? Il existe de nombreuses bibliothèques qui peuvent le faire pour vous, et bien mieux que votre code ne le ferait. Pourquoi réinventer la roue, alors qu’une fabrique de roues porte au coin de la rue les mots FOSS sur la porte?

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top