Java 当字段为可选字段时,jackson不会从json读回数据
我正在使用Java 当字段为可选字段时,jackson不会从json读回数据,java,json,java-8,jackson,optional,Java,Json,Java 8,Jackson,Optional,我正在使用Java8执行此任务。我还使用JDK8数据类型处理以下依赖项 <dependency> <groupId>com.fasterxml.jackson.datatype</groupId> <artifactId>jackson-datatype-jdk8</artifactId> <version>2.6.3</versi
Java8
执行此任务。我还使用JDK8
数据类型处理以下依赖项
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jdk8</artifactId>
<version>2.6.3</version>
</dependency>
我编写了一个测试,将一个有效的Person
对象写入一个文件,并将其读回Person
对象。我的测试是
@Test
public void writeAndReadPersonAsJsonOnFile() throws Exception {
Address address = new Address("1 Infinite Loop", "Cupertino", "CA", 95014, "USA");
String phone = "1-800-My-Apple";
Person person = new Person("john", "doe", 21, Optional.of(address), Optional.of(phone));
ObjectMapper objectMapper = registerJdkModuleAndGetMapper();
File file = temporaryFolder.newFile("person.json");
objectMapper.writeValue(file, person);
assertTrue(file.exists());
assertTrue(file.length() > 0);
Person personFromFile = objectMapper.readValue(file, Person.class);
assertEquals(person, personFromFile);
}
private ObjectMapper registerJdkModuleAndGetMapper() {
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.registerModule(new Jdk8Module());
return objectMapper;
}
作为测试的一部分创建的文件有以下内容
{
"firstName": "john",
"lastName": "doe",
"age": 21,
"address": {
"street": "1 Infinite Loop",
"city": "Cupertino",
"state": "CA",
"zip": 95014,
"country": "USA"
},
"phone": "1-800-My-Apple"
}
但当我回过头来读时,我得到了personFromFile
,如下所示
personFromFile = {Person@1178}
firstName = "john"
lastName = "doe"
age = 21
address = null
phone = null
如您所见,地址
和电话
都是空的,即使它们存在于文件中
这里怎么了
更新
代码库是。这还包含失败的测试尝试用@JsonCreator标记其中一个构造函数,告诉Jackson使用哪个构造函数。注意:这还要求您使用@JsonProperty标记构造函数的每个参数
当您希望Jackson使用构造函数或工厂方法来构造对象,而不是让Jackson使用setter或公共(非最终)字段时,您可以使用
此外,除非您为Person和Address重写“equals”,否则您的测试将不会通过
public class Person {
private String firstName;
private String lastName;
private int age;
private Optional<Address> address;
private Optional<String> phone;
public Person(String firstName, String lastName, int age) {
this(firstName, lastName, age, Optional.empty(), Optional.empty());
}
@JsonCreator
public Person(
@JsonProperty("firstName") String firstName,
@JsonProperty("lastName") String lastName,
@JsonProperty("age") int age,
@JsonProperty("address") Optional<Address> address,
@JsonProperty("phone") Optional<String> phone) {
this.firstName = firstName;
this.lastName = lastName;
this.age = age;
this.address = address;
this.phone = phone;
}
公共类人物{
私有字符串名;
私有字符串lastName;
私人互联网;
通过测试的private-Optional尝试用@JsonCreator标记其中一个构造函数,告诉Jackson要使用哪个构造函数。注意:这还要求您用@JsonProperty标记构造函数的每个参数
当您希望Jackson使用构造函数或工厂方法来构造对象,而不是让Jackson使用setter或公共(非最终)字段时,您可以使用
此外,除非您为Person和Address重写“equals”,否则您的测试将不会通过
public class Person {
private String firstName;
private String lastName;
private int age;
private Optional<Address> address;
private Optional<String> phone;
public Person(String firstName, String lastName, int age) {
this(firstName, lastName, age, Optional.empty(), Optional.empty());
}
@JsonCreator
public Person(
@JsonProperty("firstName") String firstName,
@JsonProperty("lastName") String lastName,
@JsonProperty("age") int age,
@JsonProperty("address") Optional<Address> address,
@JsonProperty("phone") Optional<String> phone) {
this.firstName = firstName;
this.lastName = lastName;
this.age = age;
this.address = address;
this.phone = phone;
}
公共类人物{
私有字符串名;
私有字符串lastName;
私人互联网;
private Optional with passing tests据我所知,Optional不会序列化,因此,如果使用默认java序列化,则在反序列化时不会获得值。但是,如果使用序列化,则应该可以
有关更多详细信息,请参阅此链接:
据我所知,optional不会序列化,因此,如果使用默认java序列化,则在反序列化时不会获得值。但是,如果使用序列化,则应该可以
有关更多详细信息,请参阅此链接:
你的例子对我来说失败了,因为地址中缺少构造函数。你确定你这里有完整的代码吗?我刚刚添加了到codebase的链接,也尝试了你所说的,但它不起作用。可能是使用3-arg构造函数。试着用@JsonCreator
标记你的构造函数。你能发布失败消息吗从JUnit开始设置?这里真正的问题是@JsonIgnore
。摆脱它,你不需要它。你的例子对我来说失败了,因为Address
中缺少构造函数。你确定这里有完整的代码吗?我刚刚添加了到codebase的链接,也尝试了你所说的,但它不起作用。它可能使用了3-arg构造函数。试着用@JsonCreator
标记你的构造函数。你能发布你从JUnit得到的失败吗?这里真正的问题是@JsonIgnore
。摆脱它,你不需要它。考虑到它们的编辑,你能解释一下这会有什么不同吗?@JsonProperty
参数的一个替代方法是使用。我不知道参数名称模块,谢谢@shmosel@SotiriosDelimanolis我为链接添加了代码示例和文档链接谢谢。但是,这里严格来说不需要@JsonCreator
。只要有无参数构造函数和适当的属性描述符,这就行了。你能解释一下这会起什么作用吗不同的是,考虑到他们的编辑?除了@JsonProperty
参数之外,另一种选择是使用。我不知道参数名称模块,谢谢@shmosel@SotiriosDelimanolis我为链接添加了代码示例和文档链接hanks。但是,这里并不严格需要@JsonCreator
。只要有无参数构造函数和适当的属性描述符,这将起作用。
public class Person {
private String firstName;
private String lastName;
private int age;
private Optional<Address> address;
private Optional<String> phone;
public Person(String firstName, String lastName, int age) {
this(firstName, lastName, age, Optional.empty(), Optional.empty());
}
@JsonCreator
public Person(
@JsonProperty("firstName") String firstName,
@JsonProperty("lastName") String lastName,
@JsonProperty("age") int age,
@JsonProperty("address") Optional<Address> address,
@JsonProperty("phone") Optional<String> phone) {
this.firstName = firstName;
this.lastName = lastName;
this.age = age;
this.address = address;
this.phone = phone;
}