【问题标题】:Setting delegate value with Groovy JsonBuilder使用 Groovy JsonBuilder 设置委托值
【发布时间】:2013-06-28 00:16:14
【问题描述】:

(这是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();
}

代码抛出 StackOverflowError,因为 第三次 调用 addUrn(在嵌套的 ratings 元素下。如果我注释掉该行,它可以完美运行(除了事实我错过了一些必要的信息)。

  1. 为什么会这样?
  2. 如何将委托设置为直接父级,例如ratings?

我尝试使用 metaClass 无济于事。

【问题讨论】:

    标签: json groovy delegates jsonbuilder


    【解决方案1】:

    这很丑陋(LOL),但会给你预期的结果:

    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()
    }
    

    注意:-

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

    直接在Groovy Web Console中测试

    【讨论】:

    • 只需添加this. 即可修复它。
    • @Devin Yea,但您还必须明智地使用大括号来获得预期的 json。
    猜你喜欢
    • 2023-03-26
    • 2011-10-24
    • 2016-07-11
    • 1970-01-01
    • 2013-06-25
    • 1970-01-01
    • 1970-01-01
    • 2014-11-03
    • 1970-01-01
    相关资源
    最近更新 更多