2016-03-21 6 views
0

Je le JSON suivant:Comment changer la valeur (et le type) d'une entrée jsonslurped de lazymap

{"name":"Guillaume","age":33,"address":"main st","pets":[{"type":"dog", "color":"brown"},{"type":"dog", "color":"brown"}]}} 

Je l'ai utilisé JsonSlurper pour l'analyser. J'ai besoin de pouvoir modifier le contenu du JSON en fonction de différents critères. Les clés que je veux modifier sont définies en externe.

Je peux facilement changer une valeur de chaîne comme suit. Le résultat ci-dessous dans le champ d'adresse dans le lazyMap étant changé de "st principale" à "deuxième st".

import groovy.json.JsonSlurper 
def slurper = new JsonSlurper() 
def result = slurper.parseText('{"person": {"name":"Guillaume","age":33,"address":"main st","pets":[{"type":"dog", "color":"brown"},{"type":"dog", "color":"brown"}]}}') 
String address = "result.person.address" // Note: this is externalized 
String newAddressValue = "second st" 
Eval.me('result', result, "$address = '$newAddressValue'") 
println result.person.address 

Le problème que je n'arrive pas à résoudre est si je veux changer la valeur d'adresse d'une chaîne à une carte.

import groovy.json.JsonSlurper 
def slurper = new JsonSlurper() 
def result = slurper.parseText('{"person": {"name":"Guillaume","age":33,"address":"main st","pets":[{"type":"dog", "color":"brown"},{"type":"dog", "color":"brown"}]}}') 

Map newAddressMap = slurper.parseText(/{"street":"Third Street", "city":"New York", "state":"New York"}/) 

Eval.me('result', result, "$address = $newAddressMap") 
println result.person.address.getClass() 
println result.person.address 

Le newAddressMap $ ci-dessus est interprétée comme une chaîne qui entraîne l'erreur suivante:

startup failed: Script1.groovy: 1: The current scope already contains a variable of the name York @ line 1, column 51. s = [city:New York, state:New York, stre

Cependant, les travaux ci-dessous (change l'adresse valeur de clé d'une chaîne à une LazyMap), mais nécessite ma clé pour être connu/codé en dur:

result.person.address = newAddressMap 
println result.person.address.getClass() 
println result.person.address 

l'erreur ne ne ci-dessous, mais le newAddressMap $ est une chaîne et la « adresse » clé lazyMap reste une chaîne. Comment puis-je modifier la valeur de la clé d'adresse d'une chaîne à une carte en ayant la valeur de la clé d'adresse définie lors de l'exécution?

Répondre

0

Voulez-vous dire par là?

import groovy.json.* 

def slurper = new JsonSlurper() 
// Given your document 
def document = slurper.parseText('{"person": {"name":"Guillaume","age":33,"address":"main st","pets":[{"type":"dog", "color":"brown"},{"type":"dog", "color":"brown"}]}}') 
// And your replacement 
def newAddressMap = slurper.parseText('{"street":"Third Street", "city":"New York", "state":"New York"}') 

// And the location of the attribute you want to replace 
def addressPath = 'person.address' 

// Split the path, and replace the property with the new map (this mutates document) 
addressPath.split('\\.').with { 
    def parent = it[0..-2].inject(document) { d, k -> d."$k" } 
    parent[it[-1]] = newAddressMap 
}  

println new JsonBuilder(document).toPrettyString() 

qui imprime:

{ 
    "person": { 
     "address": { 
      "city": "New York", 
      "state": "New York", 
      "street": "Third Street" 
     }, 
     "age": 33, 
     "name": "Guillaume", 
     "pets": [ 
      { 
       "color": "brown", 
       "type": "dog" 
      }, 
      { 
       "color": "brown", 
       "type": "dog" 
      } 
     ] 
    } 
} 
+0

C'est une approche intéressante. Mon json actuel est imbriqué et a des listes. Les champs que je veux changer peuvent varier considérablement. Par exemple, je dois pouvoir trouver et modifier les espaces réservés prédéfinis suivants dans mon json: activity [1] .person [2] .address et activity [3] .person [0] .relative [1] .address. Faire quelque chose comme Eval.me ('resultat', resultat, "$ address = '$ newAddressValue'") est attrayant car je n'ai pas besoin de marcher sur le json pour trouver le champ, mais cela semble limité à juste changer la valeur de la chaîne . – vjanzaldi

+0

D'où viennent ces espaces réservés? Eval présente un risque de sécurité important s'il s'agit d'intrants d'utilisation, et si ce n'est pas le cas, peut-être une fermeture pour chacun serait-elle préférable? De plus, mettre cette exigence dans la question nous aurait fait gagner du temps à tous les deux. –

+0

Merci pour votre réponse. J'espérais comprendre pourquoi je ne pouvais pas assigner la carte en utilisant eval. Les espaces réservés sont dérivés de la recherche à travers une instance du fichier json et recherchent des champs configurés comme des adresses de personnes ou des adresses relatives. Chaque instance du JSON peut ou non avoir les champs. Donc, ils sont dérivés du programme et non fournis par l'utilisateur. Je suis assez nouveau pour groovy et apprécie vraiment votre aide. Pouvez-vous donner un exemple de ce que vous entendez par une fermeture pour chaque placeholder? Votre contribution a aidé à mettre en œuvre une solution, alors merci. – vjanzaldi