Setting delegate value with Groovy JsonBuilder

有些话、适合烂在心里 提交于 2019-12-08 01:46:46

问题


(This is a follow up question to a question asked here)

I'm using Groovy's JsonBuilder to dynamically generate the following 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]
    }]
}

Using this code:

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

The code throws a StackOverflowError because of the third call to addUrn (under the nested ratings element. If I comment that line out, it works perfectly (other than the fact that I'm missing a necessary chunk of info).

  1. Why is this happening?
  2. How to I set the delegate to the immediate parent, e.g. ratings?

I've tried using the metaClass to no avail.


回答1:


This is pretty ugly (LOL) , but will give you the expected result:

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

Note:-

  • In the previous question, I was incorrect in saying that delegate has to refer to immediate parent. Actually it does refer to immediate parent. Instead, we have to refer to the script (which has the addUrn method) while calling the method, hence use of this when calling addUrn inside ratings. Alternatively you can ship "ratings" to a method similar to addUrn.
  • The use and sequence of parenthesis, chain brace and square brace is important what you see after "metadata". Making understand that will be cumbersome here. But only thing to keep an eye on is to stick to the basics of using method calls, declaring lists and use of closures. Try to indent each brace per line, you would be able to grab the underlying magic. :)
  • The reason for StackOverFlow error was that the method getEpisode was unable to reach the method addUrn which is owned by the script.

Test it directly in Groovy Web Console



来源:https://stackoverflow.com/questions/17355304/setting-delegate-value-with-groovy-jsonbuilder

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!