2016-08-05 69 views
0

Ich verwende Java 8, um diese Aufgabe auszuführen. Ich auch folgende Abhängigkeit arbeiten mit JDK8 Datentypen.jackson liest Daten von json nicht zurück, wenn Felder optional sind

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

Ich habe eine Klasse, die wie

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

und

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

ich ein gültiges Person Objekt in eine Datei zu schreiben, schreiben einen Test sucht und es zurück zu einem Person lesen Objekt. Mein Test ist

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

Die file erstellt als Teil der Prüfung hat folgende Inhalte

{ 
    "firstName": "john", 
    "lastName": "doe", 
    "age": 21, 
    "address": { 
     "street": "1 Infinite Loop", 
     "city": "Cupertino", 
     "state": "CA", 
     "zip": 95014, 
     "country": "USA" 
    }, 
    "phone": "1-800-My-Apple" 
} 

Aber wenn wieder zu lesen, bekomme ich personFromFile die

personFromFile = {[email protected]} 
firstName = "john" 
lastName = "doe" 
age = 21 
address = null 
phone = null 

wie folgt aussieht wie Sie sehen können , die address und phone sie beide sind null, obwohl sie in der Datei vorhanden sind.

Was ist hier falsch?

UPDATE Die Codebasis ist https://github.com/101bits/java8-optional-json. Dies enthält auch den fehlgeschlagenen Test

+0

Ihr Beispiel wegen einer fehlenden Konstruktor in 'address' für mich nicht. Sind Sie sicher, dass Sie hier vollständigen Code haben? –

+0

Ich habe gerade den Link zu Codebase hinzugefügt, auch versucht, was Sie gesagt haben, aber es funktioniert nicht – daydreamer

+0

Es ist wahrscheinlich mit dem 3-Arg-Konstruktor. Markieren Sie Ihren Konstruktor mit '@ JsonCreator'. – shmosel

Antwort

2

Versuchen Sie, einen der Konstruktoren mit @JsonCreator zu markieren, um Jackson mitzuteilen, welcher Konstruktor verwendet werden soll. Hinweis: Diese erfordert, dass Sie auch mit @JsonProperty

Sie jeweils die Konstrukteurs-Parameter markieren should use the @JsonCreator annotation, wenn Sie wünschen Jackson Objekte mit einem Konstruktor oder Factory-Methode zur Konstrukteurs im Gegensatz Jackson Setter oder öffentlichen (nicht endgültig) verwenden lassen Felder

Zusätzlich werden Ihre Tests bestehen, bis Sie für beide Person außer Kraft setzen "gleich" und

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-Adresse: Pull Request mit Durchgangstests

+0

Kannst du erklären, was das anders macht, wenn man ihre Bearbeitung betrachtet? –

+0

Eine Alternative zu den @ JsonProperty-Parametern ist die Verwendung des Moduls [Parameternamen] (https://github.com/FasterXML/jackson-module-parameter-names). – shmosel

+0

Ich wusste nicht über die Parameter-Namen-Modul, danke @shmosel – jdgilday