gpt4 book ai didi

java - Jackson,使用私有(private)字段和没有注释的 arg-constructor 反序列化类

转载 作者:搜寻专家 更新时间:2023-10-30 19:44:02 24 4
gpt4 key购买 nike

是否可以使用 Jackson 反序列化为具有私有(private)字段和自定义参数构造函数的类,而无需使用注释且无需修改类?

我知道在 Jackson 中使用这种组合是可能的:1) Java 8,2) 使用“-parameters”选项编译,以及 3) 参数名称与 JSON 匹配。但默认情况下在 GSON 中也可以不受所有这些限制。

例如:

public class Person {
private final String firstName;
private final String lastName;
private final int age;

public Person(String firstName, String lastName, int age) {
this.firstName = firstName;
this.lastName = lastName;
this.age = age;
}

public static void main(String[] args) throws IOException {
String json = "{firstName: \"Foo\", lastName: \"Bar\", age: 30}";

System.out.println("GSON: " + deserializeGson(json)); // works fine
System.out.println("Jackson: " + deserializeJackson(json)); // error
}

public static Person deserializeJackson(String json) throws IOException {
ObjectMapper mapper = new ObjectMapper();
mapper.enable(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES);
mapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY);
return mapper.readValue(json, Person.class);
}

public static Person deserializeGson(String json) {
Gson gson = new GsonBuilder().create();
return gson.fromJson(json, Person.class);
}
}

这对 GSON 很好用,但 Jackson 抛出:

Exception in thread "main" com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `jacksonParametersTest.Person` (no Creators, like default construct, exist): cannot deserialize from Object value (no delegate- or property-based Creator)
at [Source: (String)"{firstName: "Foo", lastName: "Bar", age: 30}"; line: 1, column: 2]
at com.fasterxml.jackson.databind.exc.InvalidDefinitionException.from(InvalidDefinitionException.java:67)

这在 GSON 中是可能的,所以我希望 Jackson 中一定有某种方法无需修改 Person 类,无需 Java 8,也无需显式自定义反序列化器。有人知道解决方案吗?

  • 更新、附加信息

Gson 似乎跳过了参数构造函数,因此它必须在幕后使用反射创建一个无参数构造函数。

此外,还有一个 Kotlin Jackson module它能够为 Kotlin 数据类执行此操作,即使没有“-parameters”编译器标志。所以奇怪的是,Java Jackson 似乎不存在这样的解决方案。

这是 Kotlin Jackson 中可用的(干净整洁的)解决方案(IMO 也应该通过自定义模块在 Java Jackson 中可用):

val mapper = ObjectMapper()
.enable(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES)
.registerModule(KotlinModule())

val person: Person = mapper.readValue(json, Person::class.java)

最佳答案

混合注释的解决方案

您可以使用混入注释。当修改类不是一个选项时,这是一个很好的选择。您可以将其视为一种在运行时添加更多注释的面向方面的方式,以扩充静态定义的注释。

假设您的 Person 类定义如下:

public class Person {

private final String firstName;
private final String lastName;
private final int age;

public Person(String firstName, String lastName, int age) {
this.firstName = firstName;
this.lastName = lastName;
this.age = age;
}

// Getters omitted
}

首先定义一个mix-in注解抽象类:

public abstract class PersonMixIn {

PersonMixIn(@JsonProperty("firstName") String firstName,
@JsonProperty("lastName") String lastName,
@JsonProperty("age") int age) {
}
}

然后配置 ObjectMapper 以使用定义的类作为 POJO 的混合:

ObjectMapper mapper = new ObjectMapper();
mapper.enable(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES);
mapper.addMixIn(Person.class, PersonMixIn.class);

反序列化JSON:

String json = "{firstName: \"Foo\", lastName: \"Bar\", age: 30}";
Person person = mapper.readValue(json, Person.class);

关于java - Jackson,使用私有(private)字段和没有注释的 arg-constructor 反序列化类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47570931/

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