gpt4 book ai didi

json - Grails JSONBuilder

转载 作者:行者123 更新时间:2023-12-04 14:21:05 25 4
gpt4 key购买 nike

如果我有一个简单的对象,例如

class Person {
String name
Integer age
}

我可以使用 JSONBuilder 轻松地将其用户定义的属性呈现为 JSON
def person = new Person(name: 'bob', age: 22)

def builder = new JSONBuilder.build {
person.properties.each {propName, propValue ->

if (!['class', 'metaClass'].contains(propName)) {

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

def json = builder.toString()

当属性很简单时,这很好用,即数字或字符串。但是对于更复杂的对象,例如
class ComplexPerson {
Name name
Integer age
Address address
}

class Name {
String first
String second
}

class Address {
Integer houseNumber
String streetName
String country

}

有没有一种方法可以遍历整个对象图,将每个用户定义的属性在适当的嵌套级别添加到 JSONBuilder?

换句话说,对于 ComplexPerson 的实例我希望输出是
{
name: {
first: 'john',
second: 'doe'
},
age: 20,
address: {
houseNumber: 123,
streetName: 'Evergreen Terrace',
country: 'Iraq'
}
}

更新

我不认为我可以使用 Grails JSON 转换器来做到这一点,因为我返回的实际 JSON 结构看起来像
{ status: false,
message: "some message",
object: // JSON for person goes here
}

请注意:
  • ComplexPerson 生成的 JSON是更大 JSON 对象的元素
  • 我想排除某些属性,例如 metaClassclass来自 JSON 转换

  • 如果可以将 JSON 转换器的输出作为对象获取,我可以迭代它并删除 metaClassclass属性,然后将其添加到外部 JSON 对象。

    但是,据我所知,JSON 转换器似乎只提供“全有或全无”的方法,并将其作为字符串返回输出

    最佳答案

    我终于想出了如何使用 JSONBuilder 做到这一点,这是代码

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

    您可以通过将上面的代码与以下代码一起粘贴到 grails 控制台中来进行测试
    // 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()

    它应该生成以下输出,其中将 Complex 的序列化实例存储为 object 属性的值:
    {"object": {
    "nest2": {
    "p2": "val2",
    "p1": "val1"
    },
    "nest1": {
    "p2": "val2",
    "p1": "val1"
    },
    "name": null
    }}

    关于json - Grails JSONBuilder,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5538423/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com