2014-12-19 14 views
7

Tôi có một lớp đơn giản với một nhà xây dựng tư nhân và một nhà máy tĩnh. Tôi muốn các lớp để serialize như một số, vì vậy tôi đã chú thích getter cho lĩnh vực này với @JsonValue. Tuy nhiên, Jackson dường như thích nhà xây dựng tư nhân hơn nhà máy tĩnh, ngay cả khi tôi chú thích nhà máy tĩnh với @JsonCreator. Nó hoạt động nếu tôi chú thích hàm tạo riêng với @JsonIgnore, nhưng điều đó có vẻ hơi lệch.Jackson thích xây dựng tư nhân trên @JsonCreator khi deserializing một lớp học với @JsonValue

Tôi đã xem một số bài đăng cho rằng @JsonCreator chỉ hoạt động nếu các tham số được chú thích với @JsonProperty; tuy nhiên, điều đó có vẻ là trường hợp cho các đối tượng được tuần tự hóa thành các đối tượng JSON. Đối tượng này đang được tuần tự hóa dưới dạng một số và do đó không có thuộc tính nào để cung cấp cho chú thích.

Có điều gì tôi thiếu không?

dụ lớp:

package com.example; 

import com.fasterxml.jackson.annotation.JsonCreator; 
import com.fasterxml.jackson.annotation.JsonValue; 
import com.google.common.base.Preconditions; 

public class NonNegative { 
    private final double n; 

    private NonNegative(double n) { 
    this.n = n; 
    } 

    @JsonCreator 
    public static NonNegative checked(double n) { 
    Preconditions.checkArgument(n >= 0.0); 
    return new NonNegative(n); 
    } 

    @JsonValue 
    public double getValue() { 
    return n; 
    } 

    @Override 
    public int hashCode() { 
    return Objects.hash(n); 
    } 

    @Override 
    public boolean equals(Object obj) { 
    if (this == obj) { 
     return true; 
    } 
    if (obj instanceof NonNegative) { 
     NonNegative that = (NonNegative) obj; 
     return Objects.equals(n, that.n); 
    } 
    return false; 
    } 
} 

dụ kiểm tra:

package com.example; 

import static org.assertj.core.api.Assertions.assertThat; 

import org.junit.Test; 

import com.fasterxml.jackson.databind.JsonMappingException; 
import com.fasterxml.jackson.databind.ObjectMapper; 

public class NonNegativeTest { 
    private static final ObjectMapper MAPPER = new ObjectMapper(); 

    @Test 
    public void itSerializesAndDeserializes() throws Exception { 
    NonNegative nonNegative = NonNegative.checked(0.5); 

    assertThat(MAPPER.readValue(MAPPER.writeValueAsString(nonNegative), NonNegative.class)).isEqualTo(nonNegative); 
    } 

    /* This test fails. */ 
    @Test(expected = JsonMappingException.class) 
    public void itDoesNotDeserializeANegativeNumber() throws Exception { 
    MAPPER.readValue(MAPPER.writeValueAsString(-0.5), NonNegative.class); 
    } 
} 
+0

bạn đã thử chú thích đối số của phương pháp đã chọn với @JsonProperty chưa? – wastl

+0

Tôi có. Nó không giúp được gì. – NickAldwin

+0

[Có thể có liên quan] (https://github.com/FasterXML/jackson-module-paranamer/issues/11). –

Trả lời

11

Thật vậy Jackson sẽ ghi đè phương pháp JsonCreator với phương pháp xây dựng trong trường hợp nếu tham số là Java tiêu chuẩn loại. Tôi sẽ nói đây là một lỗi trong phương thức BasicDeserializerFactory # _handleSingleArgumentConstructor. Vì vậy, vấn đề là constructor có ưu tiên cao hơn thì phương thức factory static trong trường hợp nếu constructor đó và phương thức factory tĩnh có kiểu Java thông thường. Có rất ít cách giải quyết nó.

Set tạo trình độ tầm nhìn đến NON_PRIVATE:

@JsonAutoDetect(creatorVisibility = JsonAutoDetect.Visibility.NON_PRIVATE) 
class NonNegative { 

cách thứ hai là để xóa phương thức tĩnh và sử dụng constructor. Tôi chuyển Preconditions.checkArgument để các nhà xây dựng (nó không làm được gì nhiều ... Chỉ cần ném một IllegalArgumentException nếu tình trạng không hài lòng):

public class NonNegative { 
    private final double n; 

    private NonNegative(double n) { 
    Preconditions.checkArgument(n >= 0.0); 
    this.n = n; 
    } 

    @JsonValue 
    public double getValue() { 
    return n; 
    } 
} 

Một cách khác là sử dụng chú thích @JsonIgnore nhưng bạn đề cập rằng bạn don 't thích cách tiếp cận này :)

cập nhật tôi đã đăng một lỗi: https://github.com/FasterXML/jackson-databind/issues/660

cập nhật Jackson lỗi thích constructor qua phương thức tĩnh đã được giải quyết: https://github.com/FasterXML/jackson-databind/commit/257ae1c7a88c5ccec2882433a39c0df1de2b73aa

+1

Cảm ơn, vui mừng khi thấy rằng đây là một lỗi và không phải cái gì tôi đã hiểu lầm, và rất vui mừng khi thấy rằng nó đã được giải quyết. – NickAldwin

+0

Một cách khác là sửa đổi hàm tạo nên nó sẽ không được gọi bởi Jackson, ví dụ, thêm một đối số khác (có lẽ là một đối số giả). Tôi không thấy nó tốt hơn '@ JsonIgnore' như thế nào ... – BeeOnRope

Các vấn đề liên quan