Search code examples
groovyjsonbuilder

How to use jsonbuilder to make a json which has a key named like a DefaultGroovyMethods method (identity)?


def builder = new groovy.json.JsonBuilder()
        def root = builder.auth {
            identity {
                    methods (['password'])
                    password {
                        user {
                            name {
                                usrName
                                domain {
                                    id usrDomain
                                }
                                password "openstack"
                            }
                        }
                    }
                    scope {
                        project {
                            name prjName
                            domain {
                                id 'default'
                            }
                        }
                    }
                }
            }
        assert builder.toString() == '{"auth":{"identity":{"methods":["password"],"password": {"user":{"name":"admin","domain":{"id":"default"},"password":"openstack"}}},"scope":{"project":{"name":"admin","domain":{"id":"default"}}}}}'

assert output:

    Assertion failed: 

    assert builder.toString() == '{"auth":{"identity":{"methods":["password"],"password": {"user":{"name":"admin","domain":{"id":"default"},"password":"openstack"}}},"scope":{"project":{"name":"admin","domain":{"id":"default"}}}}}'
           |       |          |
           |       |          false
           |       '{"auth":{"methods":["password"],"password":{"user":{"name":{"domain":{"id":"Default"},"password":"openstack"}}},"scope":{"project":{"name":"admin","domain":{"id":"default"}}}}}'
           {"auth":{"methods":["password"],"password":{"user":{"name":{"domain":{"id":"Default"},"password":"openstack"}}},"scope":{"project":{"name":"admin","domain":{"id":"default"}}}}}

Basically the "identity" key is ignored. I have seen that there is a method called "identity" belonging to DefaultGroovyMethods, but I have no ideea how to overcome this. First time writing Groovy, have a little background in Python. Any help is apreciated!

Complete solution done with Szymon Stepniak's answer (and other corrections to json declaration):

def builder = new groovy.json.JsonBuilder()
    builder auth: [
            identity: {
                methods(['password'])
                password {
                    user {
                        name "$usrName"
                        domain {
                            id usrDomain
                        }
                        password "openstack"

                    }
                }
            },
            scope: {
                project {
                    name prjName
                    domain {
                        id 'default'
                        }
                    }
            }
                ]
    assert builder.toString() == '{"auth":{"identity":{"methods":["password"],"password":{"user":{"name":"admin","domain":{"id":"default"},"password":"openstack"}}},"scope":{"project":{"name":"admin","domain":{"id":"default"}}}}}'

Just in case someone wants to follow along this example.


Solution

  • To overcome this limitation (closure passed to JsonBuilder.call() method resolves identity method in the delegation chain), you will need to either represent your JSON document as a map or at least use a map up to identity key and from this place you can use a closure.

    def builder = new groovy.json.JsonBuilder()
    
    builder auth: [
        identity: {
            methods (['password'])
            password {
                user {
                    name {
                        usrName
                        domain {
                            id usrDomain
                        }
                        password "openstack"
                    }
                }
            }
            scope {
                project {
                    name prjName
                    domain {
                        id 'default'
                    }
                }
            }
        }
    ]
    

    Also, keep in mind that the closure you defined does not produce the expected JSON string, but it will have identity key that you are missing in the closure example.