使用Groovy JsonBuilder设置委托值

时间:2013-06-28 00:16:15

标签: 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();
}

由于第三次StackOverflowError的调用(在嵌套的addUrn元素下),代码会抛出ratings。如果我评论该行,则可以完美(除了我缺少必要的信息块之外)。

  1. 为什么会这样?
  2. 如何将委托设置为直接父级,例如ratings
  3. 我尝试过使用metaClass无济于事。

1 个答案:

答案 0 :(得分:3)

这很丑陋(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方法)在调用方法时,因此在评级内部调用this时使用addUrn。或者,您可以将“评分”发送到类似于addUrn
  • 的方法
  • 括号,链支撑和方括号的使用和顺序非常重要,您可以在“元数据”之后看到。理解这将是繁琐的。但唯一需要关注的是坚持使用方法调用,声明列表和使用闭包的基础知识。尝试每行缩进每个大括号,你将能够抓住潜在的魔法。 :)
  • StackOverFlow错误的原因是方法getEpisode无法访问脚本所拥有的方法addUrn

直接在Groovy Web Console

中测试