如何更改jsonslurped lazymap项的值(和类型)

如何更改jsonslurped lazymap项的值(和类型),json,groovy,eval,jsonslurper,Json,Groovy,Eval,Jsonslurper,我有以下JSON: {"name":"Guillaume","age":33,"address":"main st","pets":[{"type":"dog", "color":"brown"},{"type":"dog", "color":"brown"}]}} 我已经使用JsonSlurper来解析它。我需要能够根据各种标准修改JSON的内容。我要修改的键是外部定义的 我可以很容易地更改字符串值,如下所示。以下结果导致lazyMap中的地址字段从“main st”更改为“second s

我有以下JSON:

{"name":"Guillaume","age":33,"address":"main st","pets":[{"type":"dog", "color":"brown"},{"type":"dog", "color":"brown"}]}}
我已经使用JsonSlurper来解析它。我需要能够根据各种标准修改JSON的内容。我要修改的键是外部定义的

我可以很容易地更改字符串值,如下所示。以下结果导致lazyMap中的地址字段从“main st”更改为“second 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"}]}}')

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
上面的$newAddressMap被解释为字符串,导致以下错误:

启动失败:Script1.groovy:1:当前作用域已包含 名称为York的变量@第1行,第51列。s=[城市:新 纽约州:纽约州

但是,以下操作有效(将地址键值从字符串更改为LazyMap),但需要已知/硬编码我的键:

result.person.address = newAddressMap
println result.person.address.getClass()
println result.person.address
下面的代码没有错误,但是$newAddressMap是一个字符串,lazyMap键“address”仍然是一个字符串

Eval.me('result', result, "$address = '$newAddressMap'")
println result.person.address.getClass()
println result.person.address
在运行时定义地址键值时,如何将地址键值从字符串更改为映射?

您的意思是这样的吗

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()
其中打印:

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

这是一种有趣的方法。我的实际json是嵌套的,并且有列表。我要更改的字段可能会有很大的差异。例如,我需要能够在我的json中找到并更改以下预定义占位符:活动[1]。人物[2]。地址和活动[3]。人物[0]。相对[1]。地址。执行类似Eval.me('result',result,“$address='$newAddressValue'”)它很有吸引力,因为我不必遍历json来查找字段,但它似乎仅限于更改字符串值。这些占位符来自何处?如果它们使用输入,Eval是一个相当大的安全风险,如果它们不使用,可能每个都有一个闭包会更好。此外,将此要求放在问题中会节省时间感谢您的回复。我想知道为什么我不能使用eval分配地图。占位符是通过搜索json实例并搜索配置的字段(如人员地址或相对地址)得到的。json的每个实例可能有字段,也可能没有字段。因此,它们是程序设计的Rive,不是用户提供的。我对groovy还比较陌生,非常感谢您的帮助。您能举个例子说明每个占位符的闭包是什么意思吗?您的输入帮助实现了一个解决方案,谢谢。
{
    "person": {
        "address": {
            "city": "New York",
            "state": "New York",
            "street": "Third Street"
        },
        "age": 33,
        "name": "Guillaume",
        "pets": [
            {
                "color": "brown",
                "type": "dog"
            },
            {
                "color": "brown",
                "type": "dog"
            }
        ]
    }
}