默认的 no-args 构造函数对于 Gson 是必需的吗?

2022-08-31 17:13:55

Gson 用户指南指出,我们应该为任何类定义默认的 no-args 构造函数,以便正确使用 Gson。更重要的是,在gson类的javadoc中说,如果我们尝试反序列化缺少默认构造函数的类的实例,我们将引发异常,我们应该在这种情况下使用。但是,我尝试在缺少默认构造函数的类中测试使用Gson,并且序列化和反序列化工作都没有任何问题。InstanceCreatorInstanceCreator

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

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而不需要默认构造函数,或者有任何情况下它不起作用?


答案 1

截至Gson 2.3.1。

不管 Gson 文档怎么说,如果你的类没有 no-args 构造函数,并且你还没有注册任何对象,那么它将创建一个(构造你的对象),它使用反射来获取类的方法,以创建类的实例。InstanceCreaterObjectConstructorUnsafeAllocatorallocateInstancesun.misc.Unsafe

这个不安全的类绕过了缺乏无参数构造函数的问题,并且还有许多其他危险的用途。 国家allocateInstance

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

因此,它实际上不需要构造函数,并且会绕过您的两个参数构造函数。请参阅此处的一些示例。

如果您确实有一个无参数构造函数,Gson 将使用一个使用该默认值的构造函数,方法是调用ObjectConstructorConstructor

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

我的2美分:按照 Gson 所说的操作,使用 no-arg 构造函数创建类或注册 .您可能会发现自己在使用 时处于不利的位置。InstanceCreatorUnsafe


答案 2

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

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

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

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