web-dev-qa-db-fra.com

Regex pour l'analyse d'une clé unique: valeurs extraites de JSON en Javascript

J'essaie de voir s'il est possible de rechercher une variable keys dans une chaîne JSON en Javascript et de la renvoyer par Value avec Regex. Un peu comme construire un outil de recherche JSON.

Imaginez le JSON suivant

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

Je souhaite pouvoir effectuer une recherche dans la chaîne JSON et extraire uniquement les propriétés individuelles.

supposons que c'est déjà une function, cela ressemblerait à quelque chose.

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+"\":","");    
}

Il renverrait la sous-chaîne de la Value pour la Key.

par exemple.

getPropFromJSON("Comments")

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

Si vous vous demandez pourquoi je veux faire cela au lieu d'utiliser JSON.parse(), je construis un magasin de documents JSON autour de localStorage. localStorage ne prend en charge que les paires clé/valeur, je stocke donc une chaîne JSON de la totalité de Document dans une Key unique. Je veux pouvoir exécuter une requête sur les documents, idéalement sans la surcharge de JSON.parsing(), de la Collection entière de Documents puis de la récursion sur la Keys/nested Keys pour trouver une correspondance.

Je ne suis pas le meilleur à regex donc je ne sais pas comment faire cela, ou si c'est même possible avec regex seul. Ce n'est qu'une expérience pour savoir si c'est possible. Toute autre solution pourrait être appréciée. 

12
AshHeskes

Je vous déconseillerais fortement de le faire. Le langage JSON n’est pas un langage courant comme indiqué clairement ici: https://cstheory.stackexchange.com/questions/3987/is-json-a-regular-language

Pour citer le post ci-dessus: 

Par exemple, considérons un tableau de tableaux de tableaux:

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

Il est clair que vous ne pouvez pas analyser cela avec de vraies expressions régulières.

Je vous recommande de convertir votre JSON en objet (JSON.parse) et d'implémenter une fonction de recherche pour parcourir la structure.

En dehors de cela, vous pouvez jeter un coup d'oeil aux tripes de la méthode json2.js parse de Douglas Crockford. Peut-être qu'une version modifiée vous permettrait de rechercher dans la chaîne JSON et de simplement renvoyer l'objet que vous recherchiez sans convertir l'intégralité de la structure en objet. Cela n'est utile que si vous ne récupérez jamais d'autres données à partir de votre JSON. Si vous le faites, vous pourriez aussi bien avoir tout converti pour commencer. 

EDIT 

Juste pour montrer comment Regex se décompose, voici une expression rationnelle qui tente d'analyser JSON

Si vous le branchez dans http://regexpal.com/ avec la case "Tous les points sont cochés". Vous constaterez qu'il peut correspondre à certains éléments comme:

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"

Cependant, dès que vous commencez à interroger les structures supérieures telles que "Posts", qui contient des tableaux imbriqués, vous constaterez que vous ne pouvez pas renvoyer correctement la structure car l'expression rationnelle n'a pas de contexte dans lequel "]" est la fin désignée de l'élément. structure. 

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"
          }
      ]
24
Brandon Boone

Tout d'abord, stringify l'objet JSON. Ensuite, vous devez stocker les débuts et les longueurs des sous-chaînes correspondantes. Par exemple:

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

Pour une chaîne JSON, cela fonctionne exactement de la même manière (à moins que vous ne recherchiez explicitement des virgules et des accolades, auquel cas je recommanderais une transformation préalable de votre objet JSON avant d'effectuer une expression régulière (c'est-à-dire think:, {,}).

Ensuite, vous devez reconstruire l'objet JSON. L'algorithme que j'ai créé le fait en détectant la syntaxe JSON en remontant récursivement de l'index de correspondance. Par exemple, le pseudo-code pourrait ressembler à ceci:

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

Avec ces informations, il est possible d'utiliser regex pour filtrer un objet JSON afin de renvoyer la clé, la valeur et la chaîne d'objet parent.

Vous pouvez voir la bibliothèque et le code que j'ai créés à http://json.spiritway.co/

0
mikewhit