Groovy JsonBuilder:以随机顺序序列化的对象属性

fah*_*ran 1 groovy json

我目前遇到了常规JsonBuilder的问题:我试图序列化的对象的属性以看似随机的顺序出现.

这是对象的类:

class Game {
    String title
    String gameImg2
    String description
}
Run Code Online (Sandbox Code Playgroud)

这是我一直在使用的代码:

def game = new Game(title: "a game", gameImg2: "an image", description: "desc")
def json = new JsonBuilder(game)
Run Code Online (Sandbox Code Playgroud)

从这个我希望输出是:

{"title":"a game","gameImg2":"an image", "description":"desc"}
Run Code Online (Sandbox Code Playgroud)

但相反,我得到:

{"gameImg2":"gameImg","title":"hello","description":"desc"}.
Run Code Online (Sandbox Code Playgroud)

从查看JsonBuilder示例代码看,应该维护顺序,实际上,看起来toJson方法迭代于object.properties,这是一个LinkedHashMap.我原以为这将按照它们在类中声明的顺序遍历属性.

我最好的猜测是,这与我对游戏对象的初始化有关 - 可以使用Map语法以某种方式分配属性,但同样,这似乎创建了一个应该保留顺序的LinkedHashMap.

有没有人知道我可能做错了什么或错误地假设在这里?任何线索都将是一个很大的帮助!

Asa*_*saf 5

问题是您正在将Object序列化为JSON.该对象声明了转换为Java的字段.

在Java中,不能(轻松)按声明顺序遍历字段,而JsonBuilder代码肯定不会尝试允许此行为.

查看JsonBuilder的源代码,可以看到它使用一个名为JsonOutput.groovy的类来序列化传递它的Object,如下所示:

static String toJson(object) {
    if (object == null) {
        "null"
    } else if (object instanceof Collection ||
            object.class.isArray() ||
            object instanceof Iterator ||
            object instanceof Enumeration) {
        "[" + object.collect { toJson(it) }.join(',') + "]"
    } else if (object instanceof Enum) {
        '"' + object.name() + '"'
    } else {
        def properties = object.properties
        properties.remove('class')
        properties.remove('declaringClass')
        properties.remove('metaClass')
        toJson(properties)
    }
}
Run Code Online (Sandbox Code Playgroud)

正如你所看到的代码调用性的判定,它返回对象成员对象的成员,该字段的顺序取决于JVM和未声明的顺序.

如果要维护顺序,则需要传递表示对象的映射或手动构建JSON对象.

另一种选择是编写自己的自定义构建器,这要复杂得多......