57

Gson 用户指南指出,我们应该为任何类定义默认的无参数构造函数以正确使用 Gson。更重要的是,在Gson类的javadocInstanceCreator中说,如果我们尝试反序列化缺少默认构造函数的类的实例,则会引发异常,我们应该InstanceCreator在这种情况下使用。但是,我尝试使用缺少默认构造函数的类来测试使用 Gson,并且序列化和反序列化都可以正常工作。

这是反序列化的一段代码。没有非参数构造函数的类:

public class Mushroom {
    private String name;
    private double diameter;

    public Mushroom(String name, double diameter) {
        this.name = name;
        this.diameter = diameter;
    }

    //equals(), hashCode(), etc.
}

和一个测试:

@Test
public void deserializeMushroom() {
    assertEquals(
            new Mushroom("Fly agaric", 4.0),
            new Gson().fromJson(
                    "{name:\"Fly agaric\", diameter:4.0}", Mushroom.class));
}

效果很好。

所以我的问题是:我是否可以在不需要默认构造函数的情况下实际使用 Gson,或者在任何情况下它不起作用?

4

3 回答 3

101

从 Gson 2.3.1 开始。

不管 Gson 文档怎么说,如果你的类没有无参数构造函数并且你没有注册任何InstanceCreater对象,那么它将创建一个ObjectConstructor(构造你的对象),UnsafeAllocator它使用反射来allocateInstance获取类sun.misc.Unsafe来创建你的类的实例。

这个Unsafe解决了没有无参数构造函数的问题,并且有许多其他危险的用途allocateInstance状态

分配一个实例但不运行任何构造函数。如果尚未初始化该类。

所以它实际上不需要构造函数,而是会绕过你的两个参数构造函数。在此处查看一些示例。

如果您确实有一个无参数构造函数,Gson 将使用一个通过调用ObjectConstructor使用该默认值的Constructor

yourClassType.getDeclaredConstructor(); // ie. empty, no-args

我的 2 美分:按照 Gson 所说的,使用无参数构造函数创建您的类或注册一个InstanceCreator. 您可能会发现自己在使用Unsafe.

于 2013-09-05T20:29:50.377 回答
0

Jackson库中有一个很好的解决方案,如下所述:

https://stackoverflow.com/a/11838468/2854723

关键是通过Mix-Ins 功能告诉序列化程序在使用带参数的构造函数时要使用哪些 JSON 字段。

如果该实体是外部库的一部分,那么您可以使用Creator 功能“远程注释” 。

于 2015-03-20T15:27:12.493 回答
-1

对于raindev 的示例,它可以,因为您的JSON 中包含所有值,因此即使它们没有初始化,它们也会覆盖每个变量。但在许多情况下,可能有一些瞬态字段,或在 JSON 中没有值的可选字段。然后,如果您没有无参数构造函数,则当有人尝试读取该字段时,该字段将保持为空和 NPE。

于 2021-02-09T06:09:29.523 回答