2016-08-05 2 views
0

Я использую Java 8 для выполнения этой задачи. Я также слежу за работой зависимостей с типами данных JDK8.jackson не считывает данные из json, когда поля являются необязательными

 <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 = {[email protected]} 
firstName = "john" 
lastName = "doe" 
age = 21 
address = null 
phone = null 

как вы можете видеть , address и phone оба они равны нулю, хотя они присутствуют в файле.

Что здесь не так?

UPDATE управления контентом является https://github.com/101bits/java8-optional-json. Это также содержит неудачный тест

+0

Вашего примера не может для меня из-за отсутствующий конструктор в 'Address'. У вас есть полный код здесь? –

+0

Я только что добавил ссылку на кодовую базу, также попробовал то, что вы сказали, но она не работает – daydreamer

+0

Возможно, это использование конструктора 3-arg. Попробуйте маркировать ваш конструктор с помощью '@ JsonCreator'. – shmosel

ответ

2

Попробуйте отметить один из конструкторов с помощью @JsonCreator, чтобы сообщить Jackson, какой конструктор использовать. Примечание: это также требует, чтобы отметить каждого из параметров конструктора с @JsonProperty

Вы should use the @JsonCreator annotation, когда вы хотите Джексон конструктор объектов с помощью конструктора или фабричного метода, а не позволяя Джексон использовать сеттеры или общественности (неконечное) полей

Кроме того, ваш тест не будет проходить до тех пор, пока переопределить «равно» как для лица и адрес

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

Update: Pull Request с прохождением тестов

+0

Можете ли вы объяснить, что это будет делать по-другому, учитывая их редактирование? –

+0

Альтернативой параметрам '@ JsonProperty' является использование [модуля имен параметров] (https://github.com/FasterXML/jackson-module-parameter-names). – shmosel

+0

Я не знал о модуле параметров, спасибо @shmosel – jdgilday

0

Насколько я читал необязательный, не становится сериализованным и, следовательно, при десериализации вы не получите значение, если используете стандартную java-сериализацию. Однако, если вы используете сериализацию, все должно быть хорошо.

Обратится по ссылке для получения более подробной информации: Why java.util.Optional is not Serializable, how to serialize the object with such fields

Смежные вопросы