2014-12-19 5 views
7

के साथ कक्षा को deserializing मेरे पास एक निजी निर्माता और एक स्थिर कारखाने के साथ एक साधारण वर्ग है। मैं वर्ग को एक संख्या के रूप में क्रमबद्ध करना चाहता हूं, इसलिए मैंने @JsonValue के साथ फ़ील्ड के लिए गेटर को एनोटेट किया है। हालांकि, जैक्सन स्थिर फैक्ट्री पर निजी कन्स्ट्रक्टर पसंद करते हैं, भले ही मैं स्थिर कारखाने को @JsonCreator के साथ एनोटेट करता हूं। यह काम करता है अगर मैं @JsonIgnore के साथ निजी कन्स्ट्रक्टर को एनोटेट करता हूं, लेकिन यह थोड़ा सा लगता है।जैक्सन @ जेसन क्रिएटर पर निजी कन्स्ट्रक्टर पसंद करता है जब @JsonValue

मैंने कुछ पोस्टों को दावा किया है कि @JsonCreator केवल तभी काम करता है जब पैरामीटर @JsonProperty के साथ एनोटेटेड होते हैं; हालांकि, ऐसा लगता है कि JSON ऑब्जेक्ट्स के रूप में क्रमबद्ध वस्तुओं के मामले में ऐसा लगता है। इस वस्तु को एक संख्या के रूप में क्रमबद्ध किया जा रहा है, और इस प्रकार एनोटेशन को आपूर्ति करने के लिए कोई संपत्ति नहीं है।

क्या मुझे कुछ याद आ रही है?

उदाहरण वर्ग:

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

उदाहरण परीक्षण:

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

क्या आपने @JsonProperty के साथ चेक की गई विधि के तर्क की टिप्पणी करने का प्रयास किया है? – wastl

+0

मेरे पास है। यह मदद नहीं की। – NickAldwin

+0

[शायद प्रासंगिक] (https://github.com/FasterXML/jackson- मॉड्यूल-paranamer/issues/11)। –

उत्तर

11

दरअसल जैक्सन मामले में निर्माता विधि के साथ JsonCreator विधि को पार कर जाएगी अगर पैरामीटर जावा मानक प्रकार है। मैं कहूंगा कि यह BasicDeserializerFactory # _handleSingleArgumentConstructor विधि में एक बग है।

तो, समस्या यह है कि अगर कन्स्ट्रक्टर और स्थैतिक फैक्ट्री विधि में नियमित जावा प्रकार होता है तो समस्याकार को उच्च प्राथमिकता होती है। इसे हल करने के कुछ तरीके हैं।

सेट निर्माता दृश्यता NON_PRIVATE करने का स्तर:

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

दूसरा रास्ता स्थिर कारखाने विधि हटा सकते हैं और निर्माता का प्रयोग है। मैं निर्माता को Preconditions.checkArgument ले जाया गया (अगर हालत संतुष्ट नहीं है यह ज्यादा कुछ नहीं है ... बस एक IllegalArgumentException फेंक):

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

एक और तरीका है @JsonIgnore एनोटेशन उपयोग करने के लिए है, लेकिन आप हैं जिसे आप उल्लेख https://github.com/FasterXML/jackson-databind/issues/660

अद्यतन जैक्सन बग है कि स्थिर कारखाने पद्धति पर निर्माता पसंद हल किया गया था: https://github.com/FasterXML/jackson-databind/commit/257ae1c7a88c5ccec2882433a39c0df1de2b73aa 'टी इस दृष्टिकोण :)

एक बग की तरह अद्यतन मैं प्रवेश करने के बाद

+1

धन्यवाद, यह देखकर खुशी हुई कि यह एक बग था और कुछ ऐसा नहीं था जिसे मैं गलत समझ रहा था, और यह देखकर बहुत खुशी हुई कि इसे हल किया गया है। – NickAldwin

+0

एक और तरीका कन्स्ट्रक्टर को संशोधित करना है, इसलिए इसे जैक्सन द्वारा नहीं कहा जाएगा, उदाहरण के लिए, एक और तर्क (शायद एक डमी) जोड़ना। मैं नहीं देखता कि यह '@ जेसन इग्नोर' से बेहतर कैसे है ... – BeeOnRope

संबंधित मुद्दे