c# .net regex json

c# - ¿Expresión regular para analizar una matriz de objetos JSON?



.net regex (5)

JSON por lo general no se puede analizar con expresiones regulares (ciertas variantes extremadamente simplificadas de JSON pueden, pero luego no son JSON sino algo más).

Necesita un analizador real para analizar correctamente JSON.

Y de todos modos, ¿por qué estás tratando de analizar JSON en absoluto? Existen numerosas bibliotecas que pueden hacerlo por usted, y mucho mejor que su código. ¿Por qué reinventar la rueda, cuando hay una fábrica de ruedas a la vuelta de la esquina con las palabras FOSS sobre la puerta?

Estoy tratando de analizar una matriz de objetos JSON en una matriz de cadenas en C #. Puedo extraer la matriz del objeto JSON, pero no puedo dividir la cadena de la matriz en una matriz de objetos individuales.

Lo que tengo es esta cadena de prueba:

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

En este momento estoy usando las siguientes expresiones regulares ahora mismo para dividir los elementos en objetos individuales. Por ahora son 2 expresiones regulares separadas hasta que solucione el problema con el segundo:

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

El arrayFinder regex funciona como yo lo esperaba, pero, por razones que no entiendo, el arrayParser regex no funciona en absoluto. Todo lo que quiero es dividir los elementos individuales en sus propias cadenas para obtener una lista como esta:

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

No importa si esta lista es una matriz de string[] o una colección de Group o Match , pero no estoy seguro de cómo dividir los objetos. Usando el arrayParser y la cadena json declarados anteriormente, probé este código, que supuse que no funcionaría:

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;

¿Alguien puede ver lo que estoy haciendo mal? Estoy totalmente atrapado en esto.


Los paréntesis equilibrados son literalmente un ejemplo de libro de texto de un idioma que no se puede procesar con expresiones regulares. JSON es esencialmente paréntesis equilibrado más un montón de otras cosas, con los apoyos reemplazados por parens. En la jerarquía de lenguajes formales , JSON es un lenguaje sin contexto. Las expresiones regulares no pueden analizar los lenguajes sin contexto.

Algunos sistemas ofrecen extensiones a expresiones regulares que manejan un poco las expresiones equilibradas. Sin embargo, son todos falsos hacks, todos son poco prácticos, y finalmente son la herramienta equivocada para el trabajo.

En el trabajo profesional, casi siempre usarías un analizador JSON existente. Si desea lanzar el suyo con fines educativos, le sugiero que comience con una gramática aritmética simple que admita + - * / (). (JSON tiene algunas reglas de escape que, aunque no son complejas, harán que su primer intento sea más difícil de lo necesario). Básicamente, deberá:

  1. Descomponer el lenguaje en un alfabeto de símbolos
  2. Escriba una gramática libre de contexto en términos de los símbolos que reconocen el idioma
  3. Convierta la gramática en la forma normal de Chomsky, o lo suficientemente cerca como para facilitar el paso 5
  4. Escriba un lexer que convierta el texto en bruto en su alfabeto de entrada
  5. Escriba un analizador de descenso recursivo que tome la salida de su lexer, lo analice y produzca algún tipo de salida

Esta es una asignación típica de CS de tercer año en casi cualquier universidad.

El siguiente paso es descubrir cuán compleja es la cadena JSON que necesita para desencadenar un desbordamiento de pila en su analizador recursivo. Luego observe los otros tipos de analizadores que se pueden escribir, y comprenderá por qué cualquiera que tenga que analizar un idioma sin contexto en el mundo real usa una herramienta como yacc o antlr en lugar de escribir un analizador a mano.

Si eso es más aprendizaje de lo que estabas buscando, entonces no dudes en utilizar un analizador sintáctico JSON estándar, satisfecho de haber aprendido algo importante y útil: los límites de las expresiones regulares.


Los paréntesis equilibrados son literalmente un ejemplo de libro de texto de un idioma que no se puede procesar con expresiones regulares

bla bla bla ... mira esto:

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

esto funciona para mí

si quiere hacer coincidir los valores vacíos, cambie el último ''+'' a ''*''


¿Estás usando .NET 3.5? Si es así, puede usar DataContractJsonSerializer para analizar esto. No hay razón para hacer esto usted mismo.

Si no está usando .NET 3.5, puede usar 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; }

Esta función implementa la expresión regular de Lukasz. Solo agrego a inclide + char al grupo de valores (porque estoy usando eso para analizar el token de autenticación de conexión en vivo)