繁体   English   中英

当字段为可选时,杰克逊不会从json读取数据

[英]jackson does not read back data from json when fields are Optional

我正在使用Java 8执行此任务。 我还遵循与JDK8数据类型的依赖关系。

        <dependency>
            <groupId>com.fasterxml.jackson.datatype</groupId>
            <artifactId>jackson-datatype-jdk8</artifactId>
            <version>2.6.3</version>
        </dependency>

我有一堂课,看起来像

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;

import java.util.Optional;

public class Person {
    private String firstName;
    private String lastName;
    private int age;
    private Optional<Address> address;
    private Optional<String> phone;

    private Person() {
    }

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

    public Person(String firstName, String lastName, int age,
                  Optional<Address> address, Optional<String> phone) {
        this.firstName = firstName;
        this.lastName = lastName;
        this.age = age;
        this.address = address;
        this.phone = phone;
    }

    public String getFirstName() {
        return firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public int getAge() {
        return age;
    }

    @JsonIgnore
    public Optional<Address> getAddress() {
        return address;
    }

    @JsonIgnore
    public Optional<String> getPhone() {
        return phone;
    }

    @JsonProperty("address")
    private Address getAddressForJson(){
        return address.orElse(null);
    }

    @JsonProperty("phone")
    private String getPhoneForJson() {
        return phone.orElse(null);
    }
}

public class Address {
    private String street;
    private String city;
    private String state;
    private int zip;
    private String country;

    public Address(String street, String city, String state, int zip, String country) {
        this.street = street;
        this.city = city;
        this.state = state;
        this.zip = zip;
        this.country = country;
    }

    public String getStreet() {
        return street;
    }

    public String getCity() {
        return city;
    }

    public String getState() {
        return state;
    }

    public int getZip() {
        return zip;
    }

    public String getCountry() {
        return country;
    }
}

我编写了一个测试,将有效的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;
    }

作为测试的一部分创建的file具有以下内容

{
    "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

如您所见,即使文件中存在addressphone它们都为空。

怎么了

更新代码库为https://github.com/101bits/java8-optional-json 这也包含失败的测试

尝试用@JsonCreator标记一个构造函数,以告诉Jackson使用哪个构造函数。 注意:这还要求您使用@JsonProperty标记每个构造函数的参数

当您希望Jackson用构造函数或工厂方法构造对象时, 应该使用@JsonCreator批注 ,而不是让Jackson使用setter或public(非最终)字段

此外,您必须先覆盖“个人”和“地址”的“等于”,然后才能通过测试

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;
    }

更新:通过测试的拉取请求

据我所读,Optional不会序列化,因此,在反序列化时,如果使用默认的Java序列化,则不会获得该值。 但是,如果您使用序列化,那应该没问题。

请参阅此链接以获取更多详细信息: 为什么java.util.Optional不可序列化,如何使用此类字段序列化对象

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM