2016-08-05 13 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> 

私は、ファイルに有効なPersonオブジェクトを作成し、そしてPersonにそれをリードバックするテストを書く

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

のように見えるクラスを持っていますオブジェクト。私のテストは

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

を以下のようになりますpersonFromFileを取得していますaddressphoneこれらは両方ともファイルに存在していてもnullです。

ここで何が間違っていますか?

更新 コードベースはhttps://github.com/101bits/java8-optional-jsonです。これには失敗したテストも含まれます

+0

あなたの例では、理由Address' 'で行方不明コンストラクタの私のために失敗しました。ここに完全なコードがありますか? –

+0

私はcodebaseへのリンクを追加しましたが、あなたが言ったことも試しましたが、うまくいきません – daydreamer

+0

おそらく3引数のコンストラクタを使用しています。あなたのコンストラクタを '@ JsonCreator'でマークしてみてください。 – shmosel

答えて

2

コンストラクタの1つを@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; 
    } 

更新:合格テストと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

関連する問題