json - 使用 Groovy JsonBuilder 设置委托(delegate)值

标签 json groovy delegates jsonbuilder

(这是对所提问题 here 的后续问题)

我使用 Groovy 的 JsonBuilder 动态生成以下 JSON:

{
    "type": {
        "__type": "urn",
        "value": "myCustomValue1"
    },
    "urn": {
        "__type": "urn",
        "value": "myCustomValue2"
    },
    "date": {
        "epoch": 1265662800000,
        "str": "2010-02-08T21:00:00Z"
    },
    "metadata": [{
        "ratings": [{
            "rating": "NR",
            "scheme": "eirin",
            "_type": {
                "__type": "urn",
                "value": "myCustomValue3"
            }
        }],
        "creators": [Jim, Bob, Joe]
    }]
}

使用此代码:

def addUrn(parent, type, urnVal) {
    parent."$type" {
        __type "urn"
        "value" urnVal
    }
}

String getEpisode(String myCustomVal1, String myCustomVal2, String myCustomVal3) {    
    def builder = new groovy.json.JsonBuilder()
    builder {
        addUrn(delegate, "type", myCustomVal1)
        addUrn(delegate, "urn", "some:urn:$myCustomVal2")
        "date" {
            epoch 1265662800000
            str "2010-02-08T21:00:00Z"
        }
       "metadata" ({
                ratings ({
                        rating "G"
                        scheme "eirin"
                        addUrn(delegate, "_type", "$myCustomVal3")
                })
                creators "Jim", "Bob", "Joe"                    
        })
    }

    return root.toString();
}

由于第三次调用addUrn(在嵌套的 ratings元素下),代码抛出了StackOverflowError。如果我注释掉该行,它就会完美地工作(除了我丢失了必要的信息 block 这一事实)。

  1. 为什么会发生这种情况?
  2. 如何将委托(delegate)设置为直接父级,例如评分

我尝试过使用元类,但没有成功。

最佳答案

这很难看(笑),但会给你预期的结果:

def addUrn(parent, type, urnVal) {
    parent."$type" {
        __type "urn"
        "value" urnVal
    }
}

String getEpisode(String myCustomVal1, String myCustomVal2, String myCustomVal3) {
    def builder = new groovy.json.JsonBuilder()
    def root = builder {
        addUrn(delegate, "type", myCustomVal1)
        addUrn(delegate, "urn", "some:urn:$myCustomVal2")
        "date" {
            epoch 1265662800000
            str "2010-02-08T21:00:00Z"
        }
        "metadata" ([{([
                "ratings" ([{
                        rating "G"
                        scheme "eirin"
                        this.addUrn(delegate, "_type", "$myCustomVal3")
                }]),
                creators ("Jim", "Bob", "Joe")
        ])}])
    }

    println builder.toPrettyString()
}

注意:-

  • 在上一个问题中,我错误地表示委托(delegate)已 指代直系父辈。实际上它确实指的是立即 parent 。相反,我们必须引用脚本(其中包含 addUrn 方法),同时调用该方法,因此在评级内调用 addUrn 时使用 this。或者,您可以将“评级”发送到类似于 addUrn 的方法。
  • 括号、链括号和方括号的使用和顺序对于您在“元数据”之后看到的内容很重要。在这里理解这一点会很麻烦。但唯一需要注意的是坚持使用方法调用、声明列表和使用闭包的基础知识。尝试缩进每行的每个大括号,您将能够捕获底层的魔力。 :)
  • StackOverFlow 错误的原因是 getEpisode 方法无法访问脚本拥有的 addUrn 方法。

直接在Groovy Web Console中测试一下

关于json - 使用 Groovy JsonBuilder 设置委托(delegate)值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17355304/

相关文章:

iphone - 如何在 iPhone 中将 UIImage 转换为 JSON 文件?

java - 每 'when' 步执行 Action Spock

c# - 为什么这个 OrderBy 参数是错误的?

macos - Swift 弱委托(delegate)运行时错误(访问错误)。漏洞?

javascript - 如何使用 Angularjs 从 json 中删除字符串中的数字?

javascript - 来自 json 的微数据

java - 接收和输出 JSON 错误消息 Android

svn - 使用 Jenkins 管道中的凭据检查 SVN?

grails - Grails Mail Plugin无法安装-尝试在Config中修复,但仍然无法正常工作

c# - 通过匿名委托(delegate)取消订阅事件