Expression régulière pour analyser un tableau d'objets JSON?

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

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

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

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

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

le arrayFinder regex fonctionne comme je l'espérais mais, pour des raisons que je ne comprends pas, le arrayParser regex ne fonctionne pas du tout. Tout ce que je veux c'est diviser les éléments individuels en leurs propres cordes donc je reçois une liste comme ceci:

{id:0,name:"Lorem Ipsum"}

{id:1,name:"Lorem Ipsum"}

{id:2,name:"Lorem Ipsum"}

si cette liste est un tableau string[] ou une collection Group ou Match n'a pas d'importance, mais je suis perplexe quant à la façon de diviser les objets. En utilisant le arrayParser et la chaîne de caractères json déclarée ci-dessus, j'ai essayé ce code que j'ai supposé ne fonctionnerait pas avec de la chance:

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;

est-ce que quelqu'un peut voir ce que je fais de mal? Je suis totalement coincé sur cette.

11
demandé sur Dan Herbert 2009-01-03 06:53:06

5 réponses

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 est essentiellement équilibré entre parenthèses plus un tas d'autres choses, avec les accolades remplacé par parens. Dans la hiérarchie des langues formelles , JSON est une langue sans contexte. Les expressions régulières ne peuvent pas analyser des langues sans contexte.

certains systèmes offrent des extensions à des expressions régulières que kinda-sorta manipuler des expressions équilibrées. Cependant, ils sont tous moches, ils sont tous importables, et ils sont tous finalement le mauvais outil pour le travail.

dans le travail professionnel, vous utiliseriez presque toujours un analyseur JSON existant. Si vous voulez faire rouler votre propre à des fins éducatives alors je suggérerais de commencer par une simple grammaire arithmétique qui soutient + - * / ( ). (JSON a quelques règles d'évasion qui, bien que pas complexe, rendra votre première tentative plus difficile qu'il n'a besoin d'être.) En gros, vous aurez besoin de:

  1. décomposer la langue en un alphabet de symboles
  2. écrire une grammaire sans contexte en termes de ces symboles qui reconnaîtla langue
  3. convertir la grammaire en Chomsky forme normale, ou assez près pour rendre l'étape 5 facile
  4. écrire une lexer qui convertit le texte brut dans votre alphabet d'entrée
  5. écrivez un analyseur de descente récursif qui prend votre lexer's output, le analyse, et produit une sorte de sortie

il s'agit d'une affectation CS typique de troisième année à peu près n'importe quelle université.

la prochaine étape est de découvrir la complexité d'une chaîne JSON dont vous avez besoin pour déclencher un débordement de pile dans votre parser récursif. Ensuite, regardez les autres types d'analyseurs qui peuvent être écrits, et vous comprendrez pourquoi quiconque doit analyser un langage sans contexte dans le monde réel utilise un outil comme yacc ou antlr au lieu d'écrire un analyseur à la main.

si c'est plus apprendre que ce que vous cherchiez, alors vous devriez vous sentir libre d'utiliser un analyseur JSON standard, rassuré que vous avez appris quelque chose d'important et utile: les limites des expressions régulières.

37
répondu user51099 2009-01-03 05:11:47

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 ... regardez ça:

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

cela fonctionne pour moi

si vous voulez faire correspondre les valeurs vides, changez la dernière '+' en ' * '

11
répondu 2009-08-23 10:28:56

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

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

6
répondu casperOne 2011-09-01 12:18:48
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 Lukasz. J'ajoute seulement au groupe incride + char à la valeur (parce que j'utilise cela pour analyser le token auth Live connect)

1
répondu Брайков 2012-01-22 13:57:40

JSON ne peut pas typiquement être interprété avec des expressions régulières (certaines variantes extrêmement simplifiées de JSON peuvent, mais alors ils ne sont pas JSON mais quelque chose d'autre).

vous avez besoin d'un analyseur réel pour analyser correctement JSON.

et de toute façon, pourquoi essayez-vous de parser JSON? Il existe de nombreuses bibliothèques qui peut le faire pour vous, et beaucoup mieux que votre code. Pourquoi réinventer la roue quand il y a une roue autour de l'usine un coin avec les mots FOSS au-dessus de la porte?

0
répondu yfeldblum 2009-01-03 05:13:53