Grails JSONBuilder

前端 未结 2 617
说谎
说谎 2020-12-01 08:22

If I have a simple object such as

class Person {
  String name
  Integer age
}

I can easily render it\'s user-defined properties as JSON us

2条回答
  •  清歌不尽
    2020-12-01 09:21

    I finally figured out how to do this using a JSONBuilder, here's the code

    import grails.web.*
    
    class JSONSerializer {
    
        def target
    
        String getJSON() {
    
            Closure jsonFormat = {   
    
                object = {
                    // Set the delegate of buildJSON to ensure that missing methods called thereby are routed to the JSONBuilder
                    buildJSON.delegate = delegate
                    buildJSON(target)
                }
            }        
    
            def json = new JSONBuilder().build(jsonFormat)
            return json.toString(true)
        }
    
        private buildJSON = {obj ->
    
            obj.properties.each {propName, propValue ->
    
                if (!['class', 'metaClass'].contains(propName)) {
    
                    if (isSimple(propValue)) {
                        // It seems "propName = propValue" doesn't work when propName is dynamic so we need to
                        // set the property on the builder using this syntax instead
                        setProperty(propName, propValue)
                    } else {
    
                        // create a nested JSON object and recursively call this function to serialize it
                        Closure nestedObject = {
                            buildJSON(propValue)
                        }
                        setProperty(propName, nestedObject)
                    }
                }
            }
        }
    
       /**
         * A simple object is one that can be set directly as the value of a JSON property, examples include strings,
         * numbers, booleans, etc.
         *
         * @param propValue
         * @return
         */
        private boolean isSimple(propValue) {
            // This is a bit simplistic as an object might very well be Serializable but have properties that we want
            // to render in JSON as a nested object. If we run into this issue, replace the test below with an test
            // for whether propValue is an instanceof Number, String, Boolean, Char, etc.
            propValue instanceof Serializable || propValue == null
        }
    }
    

    You can test this by pasting the code above along with the following into the grails console

    // Define a class we'll use to test the builder
    class Complex {
        String name
        def nest2 =  new Expando(p1: 'val1', p2: 'val2')
        def nest1 =  new Expando(p1: 'val1', p2: 'val2')
    }
    
    // test the class
    new JSONSerializer(target: new Complex()).getJSON()
    

    It should generate the following output which stores the serialized instance of Complex as the value of the object property:

    {"object": {
       "nest2": {
          "p2": "val2",
          "p1": "val1"
       },
       "nest1": {
          "p2": "val2",
          "p1": "val1"
       },
       "name": null
    }}
    

提交回复
热议问题