【问题标题】:Groovy JsonBuilder: object properties being serialized in random orderGroovy JsonBuilder:以随机顺序序列化的对象属性
【发布时间】:2012-06-13 22:14:22
【问题描述】:

我目前在使用 groovy JsonBuilder 时遇到问题:我尝试序列化的对象的属性似乎以随机顺序出现。

这是对象的类:

class Game {
    String title
    String gameImg2
    String description
}

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

def game = new Game(title: "a game", gameImg2: "an image", description: "desc")
def json = new JsonBuilder(game)

据此,我希望输出是:

{"title":"a game","gameImg2":"an image", "description":"desc"}

但相反,我得到:

{"gameImg2":"gameImg","title":"hello","description":"desc"}.

从JsonBuilder example code来看,似乎应该保持顺序,实际上,看起来toJson方法迭代了object.properties,它是一个LinkedHashMap。我原以为这会按照它们在类中声明的顺序遍历属性。

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

有没有人知道我在这里做错了什么或错误假设?任何线索都会有很大帮助!

【问题讨论】:

  • 订单重要吗? JSON 对象没有排序,是吗? (我不知道,我在问。)
  • [JSON.org] 声明 一个对象是一组无序的名称/值对,没有任何 JSON 解析器值得盐分依赖于特定的顺序。
  • @DaveNewton 你是对的,JSON 对象不保证任何迭代顺序(与 JavaScript 对象相同)。来自json.org:“object 是一组无序的名称/值对”。

标签: json groovy


【解决方案1】:

问题是您将对象序列化为 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)
    }
}

如你所见,代码调用对象的 properies 成员返回对象成员,字段的顺序取决于 JVM,而不是声明的顺序。

如果您想保持顺序,您需要传入表示对象的映射或手动按顺序构建 JSON 对象。

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

【讨论】:

  • 实际上,java(至少 8+)以声明的顺序返回声明的字段。以及由 groovy 停止的订单... object.properties 最终调用 groovy.lang.MetaClassImpl.getProperties() 使用非链接映射来收集属性:-|
  • Java 8 实际上确实以声明的顺序返回字段,但这是 JVM 特定的,在 JSR 中没有定义。正如javadoc 所说:“返回数组中的元素没有排序,也没有任何特定的顺序。”
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-02-19
  • 1970-01-01
  • 2019-04-04
  • 2014-06-12
  • 2018-08-07
相关资源
最近更新 更多