2012-01-05 11 views
9

estoy tratando de ver si es posible las operaciones de búsqueda individuales keys de una cadena JSON en Javascript y volver es Value con Regex. Algo así como construir una herramienta de búsqueda JSON.expresiones regulares para analizar individuales fundamentales: los valores de JSON en Javascript

Imagine la siguiente JSON

"{ 
    "Name": "Humpty", 
    "Age": "18", 
    "Siblings" : ["Dracula", "Snow White", "Merlin"], 
    "Posts": [ 
     { 
      "Title": "How I fell", 
      "Comments": [ 
       { 
        "User":"Fairy God Mother", 
        "Comment": "Ha, can't say I didn't see it coming" 
       } 
      ] 
     } 
    ] 
}" 

Quiero ser capaz de buscar a través de la cadena JSON y sólo tire de propiedades individuales.

supongamos que es un function ya, se vería algo así como.

function getPropFromJSON(prop, JSONString){ 
    // Obviously this regex will only match Keys that have 
    // String Values. 
    var exp = new RegExp("\""+prop+"\"\:[^\,\}]*"); 
    return JSONString.match(exp)[0].replace("\""+prop+"\":","");  
} 

volvería la subcadena de la Value para la Key.

p. Ej.

getPropFromJSON("Comments") 

> "[ 
    { 
     "User":"Fairy God Mother", 
     "Comment": "Ha, can't say I didn't see it coming" 
    } 
]" 

Si su preguntando por qué quiero hacer esto en lugar de utilizar JSON.parse(), estoy construyendo un almacén de documentos JSON alrededor localStorage. localStorage solo admite pares clave/valor, por lo que estoy almacenando una cadena JSON de Document en un único Key. Quiero poder ejecutar una consulta en los documentos, idealmente sin la sobrecarga de JSON.parsing()Collection de Documents y luego recurrir sobre el Keys/Keys anidado para encontrar una coincidencia.

No soy el mejor en regex así que no sé cómo hacer esto, o si es posible con regex solo. Este es solo un experimento para descubrir si es posible. Cualquier otra idea como una solución sería apreciada.

+8

Esto se JSON, ¿por qué no acaba de abordar como JSON? – fge

+3

@fge si lees su publicación, verás por qué. Aunque no es realmente una razón válida para usar regex. Recuerde que la expresión regular es un lenguaje REGULAR ... y no debería usarse para este – AlanFoster

+1

. Dudo que valga la pena implementar su propio análisis sintáctico para esto.Puede funcionar mejor si solo necesita un único valor de un documento enorme, pero si realiza varias búsquedas, mantener el json en la memoria debe ser más rápido. – Kapep

Respuesta

19

Lo desanimaría fuertemente a hacer esto. JSON no es un lenguaje regular como claramente se indica aquí: https://cstheory.stackexchange.com/questions/3987/is-json-a-regular-language

citar el post anterior:

Por ejemplo, considere un conjunto de matrices de matrices:

[ [ [ 1, 2], [2, 3] ] , [ [ 3, 4], [ 4, 5] ] ] 

Es evidente que no podías 't analizar eso con expresiones regulares verdaderas.

Recomendaría convertir su JSON a un objeto (JSON.parse) & implementando una función de búsqueda para atravesar la estructura.

Aparte de eso, puede echar un vistazo a las agallas de Douglas Crockford's json2.js método de análisis. Tal vez una versión alterada le permita buscar a través de la cadena JSON & simplemente devuelva el objeto particular que estaba buscando sin convertir la estructura completa a un objeto. Esto solo es útil si nunca recupera ningún otro dato de su JSON. Si lo haces, igual podrías haber convertido todo para comenzar.

EDITAR

Sólo para mostrar con más detalle cómo Regex se rompe, esto es una expresión regular que intenta analizar JSON

Si lo conecta a http://regexpal.com/ con "Dot coincide con todos los" marcada. Usted encontrará que puede coincidir con algunos elementos muy bien como:

Regex

"Comments"[ :]+((?=\[)\[[^]]*\]|(?=\{)\{[^\}]*\}|\"[^"]*\") 

JSON Matched

"Comments": [ 
       { 
        "User":"Fairy God Mother", 
        "Comment": "Ha, can't say I didn't see it coming" 
       } 
      ] 

Regex

"Name"[ :]+((?=\[)\[[^]]*\]|(?=\{)\{[^\}]*\}|\"[^"]*\") 

JSON Matched

"Name": "Humpty" 

Sin embargo, tan pronto como empiece a realizar consultas sobre las estructuras superiores como "Mensajes", que ha anidado matrices, encontrará que no se puede devolver correctamente la estructura ya que el regex no tiene contexto de que "]" es el final designado de la estructura.

Regex

"Posts"[ :]+((?=\[)\[[^]]*\]|(?=\{)\{[^\}]*\}|\"[^"]*\") 

JSON Matched

"Posts": [ 
    { 
     "Title": "How I fell", 
     "Comments": [ 
      { 
       "User":"Fairy God Mother", 
       "Comment": "Ha, can't say I didn't see it coming" 
      } 
     ] 
+1

Eché un vistazo al método de análisis json2.js anteriormente. Realmente no hace ningún tipo de análisis sintáctico. Simplemente reemplaza mucho los caracteres/contenidos/scripts malos/peligrosos/escapados para que el JSON esté limpio. Luego pasa la cadena limpia a 'eval();'. Creo que tienes razón al usar el tema 'Regex' solo. Voy a intentar usar una combinación de 'JS' y' Regex'. Estoy en desacuerdo sobre la conversión de todo y atravesarlo, para mi caso de uso. Sería demasiado intensivo en grandes 'colecciones || documentos', sin mencionar la búsqueda y coincidencia en múltiples propiedades. – AshHeskes

+0

Bastante justo. Solo otra cosa que podría recomendar (y no soy un experto en este campo) es usar un formato que sea amigable con los datos relacionales. Supongo que Ms-Sql, MySql y Oracle tienen formas óptimas de almacenar los datos, por lo que leer, escribir, comparar y unir datos es muy rápido (y dudo que esté almacenado como JSON). Solo un pensamiento. –

+1

Debe seguir los consejos en esta respuesta y evitar hacerlo a través de cualquier método que no sea deserializar adecuadamente el JSON y buscar a través de la estructura resultante. – JAAulde

0

En primer lugar, stringify el objeto JSON. Luego, debe almacenar los inicios y las longitudes de las subcadenas coincidentes. Por ejemplo:

"matched".search("ch") // yields 3 

para una cadena JSON, esto funciona exactamente de la misma (a menos que usted está buscando explícitamente comas y corchetes en cuyo caso te recomiendo transformar algunas antes de su objeto JSON antes de realizar expresiones regulares (es decir, pensar:, {,}).

A continuación, debe reconstruir el objeto JSON. El algoritmo que creé lo hace al detectar la sintaxis JSON retrocediendo recursivamente desde el índice del partido. Por ejemplo, el pseudo código podría verse como sigue:

find the next key preceding the match index, call this theKey 
then find the number of all occurrences of this key preceding theKey, call this theNumber 
using the number of occurrences of all keys with same name as theKey up to position of theKey, traverse the object until keys named theKey has been discovered theNumber times 
return this object called parentChain 

Con esta información, es posible usar regex para filtrar un objeto JSON para devolver la clave, el valor y la cadena de objetos padre.

Se puede ver la biblioteca y el código de mi autoría en http://json.spiritway.co/

Cuestiones relacionadas