2013-07-01 4 views
34

यह कोई डुप्लिकेट सवाल यह है कि क्योंकि निम्न प्रश्नों या तो गंदा कर रहे हैं या वे बिल्कुल नहीं दिए गए हैं:क्या जैक्सन वास्तव में जेसन को जेनेरिक प्रकार में deserialize करने में असमर्थ है?

deserializing-a-generic-type-with-jackson

jackson-deserialize-into-runtime-specified-class

jackson-deserialize-using-generic-class

jackson-deserialize-generic-class-variable

मैं इस आशा है कि सवाल अंततः एक उत्तर मिलेगा जो इसे अच्छे के लिए स्पष्ट करता है।

एक मॉडल होने:

public class AgentResponse<T> { 

    private T result; 

    public AgentResponse(T result) { 
     this.result = result; 
    } 
    public T getResult() { 
     return result; 
    } 
} 

JSON इनपुट:

{"result":{"first-client-id":3,"test-mail-module":3,"third-client-id":3,"second-client-id":3}} 

और दो की सिफारिश की सामान्य प्रकार deserializing के तरीके:

mapper.readValue(out, new TypeReference<AgentResponse<Map<String, Integer>>>() {}); 

या

JavaType javaType = mapper.getTypeFactory().constructParametricType(AgentResponse.class, Map.class); 
mapper.readValue(out, javaType); 

जैक्सन जेनेरिक टाइप टी से निपटने में कभी भी सक्षम नहीं है, यह आंकड़े जावाटाइप से एक मानचित्र है, लेकिन यह टाइप एरर के कारण ऑब्जेक्ट टाइप कन्स्ट्रक्टर तर्क पाता है और एक त्रुटि फेंकता है। तो क्या यह जैक्सन बग है, या क्या मैं कुछ गलत कर रहा हूं? TypeReference या JavaType के स्पष्ट विनिर्देश क्या है?

com.fasterxml.jackson.databind.JsonMappingException: No suitable constructor found for type [simple type, class com.fg.mail.smtp.AgentResponse<java.util.Map<java.lang.String,java.lang.Integer>>]: can not instantiate from JSON object (need to add/enable type information?) 
at [Source: [email protected]; line: 1, column: 2] 
at com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:164) 
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromObjectUsingNonDefault(BeanDeserializerBase.java:984) 
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:276) 
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:121) 
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:2888) 
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2064) 
+0

आपको जैक्सन-उपयोगकर्ता मेलिंग सूची – fge

+0

पर उस प्रश्न को पोस्ट करना चाहिए, साथ ही, क्या आप सचमुच कोशिश करते हैं और deserialize _all_ कि JSON या सिर्फ यह JSON का 'परिणाम' सदस्य मान है? – fge

+0

मैं जेएसओएन इनपुट को एजेंट रेस्पॉन्स में deserializing कर रहा हूँ। मुझे नहीं पता कि मैं इसे आंशिक रूप से कैसे और क्यों निराश करूंगा। यह स्थिति और परिणाम मूल्य के साथ सिर्फ एक प्रतिक्रिया है, जो ऑब्जेक्ट, संग्रह, मानचित्र इत्यादि हो सकता है। मैंने प्रश्न को संशोधित किया है, इसलिए केवल सामान्य परिणाम है, – lisak

उत्तर

49

आपको जैक्सन को ऑब्जेक्ट बनाने के तरीके को बताने के लिए कन्स्ट्रक्टर पर कुछ एनोटेशन जोड़ने की आवश्यकता है। मेरे लिए काम किया है:

public class AgentResponse<T> { 

    private T result; 

    @JsonCreator 
    public AgentResponse(@JsonProperty("result") T result) { 
     this.result = result; 
    } 
    public T getResult() { 
     return result; 
    } 
} 

@JsonCreator एनोटेशन के बिना, जैक्सन इस निर्माता कॉल करने के लिए पता नहीं कर सकते हैं। और @JsonProperty एनोटेशन के बिना, जैक्सन को पता नहीं है कि कन्स्ट्रक्टर के पहले तर्क result संपत्ति पर मानचित्र हैं।

+3

मैन आपने अपना दिन बचाया, मैं जैकसन स्टैक को सभी तरह से नीचे डिबग कर रहा था और मैंने देखा कि इसे कन्स्ट्रक्टर तर्क मिला है, इसलिए मैंने सोचा कि यह सामान्य समस्या थी। असल में असली समस्या यह थी कि जैक्सन कन्स्ट्रक्टर तर्क नामों को नहीं जानता था क्योंकि जेवीएम इसे प्रदान नहीं करता है। अरे मुझे पहले जेनेरिक के बिना कोशिश करनी चाहिए ... धन्यवाद! – lisak

+4

और यदि आप कक्षा को सीधे एनोटेट करने में असमर्थ हैं या अनिच्छुक हैं, तो आप इसके बजाय एक मिश्रण को एनोटेट कर सकते हैं: http://wiki.fasterxml.com/JacksonMixInAnnotations – dnault

4

मैंने एक ही दृष्टिकोण का उपयोग करने की कोशिश की लेकिन मैंने अपनी मॉडल कक्षा को एनोटेट नहीं किया है। इसने मेरे लिए अच्छा काम किया।

यह मेरा मॉडल वर्ग

public class BasicMessage<T extends Serializable> implements Message<T> { 
    private MessageHeader messageHeader = new MessageHeader(); 
    private T payload; 
    public MessageHeader getHeaders() { 
     return messageHeader; 
    } 

    public Object getHeader(String key) { 
     return messageHeader.get(key); 
    } 

    public Object addHeader(String key, Object header) { 
     return messageHeader.put(key, header); 
    } 

    public T getPayload() { 
     return payload; 
    } 

    public void setPayload(T messageBody) { 
     this.payload = messageBody; 
    } 
} 

है और मैं पेलोड

public static <T extends Serializable> BasicMessage<T> getConcreteMessageType(String jsonString, Class<T> classType) { 
     try { 
      ObjectMapper mapper = new ObjectMapper(); 
      JavaType javaType = mapper.getTypeFactory().constructParametricType(BasicMessage.class, classType); 
      return mapper.readValue(jsonString, javaType); 
     } catch (IOException e) { 

     } 
} 

जहां jsonString एक स्ट्रिंग में BasicMessageObject शामिल deserializing के लिए निम्न विधि का इस्तेमाल किया।

+0

+1 ... अभी भी आप बनाए गए ऑब्जेक्ट की अपरिवर्तनीयता खो देंगे। या यह निजी सेटर्स के साथ भी संभव है? – Karussell

1

JSON स्ट्रिंग जिसे deserialized करने की आवश्यकता है पैरामीटर T के बारे में प्रकार की जानकारी शामिल होना होगा।
आपको क्लास T कक्षा AgentResponse पर पैरामीटर T के रूप में पारित किया जा सकता है ताकि पैरामीटर प्रकार T के बारे में प्रकार की जानकारी जैक्सन द्वारा जेएसओएन स्ट्रिंग से लिखी/लिखी जा सके।

मान लीजिए कि T कोई वर्ग हो सकता है जो अमूर्त वर्ग Result फैलाता है।

public class AgentResponse<T extends Result> { 
    public Hits<T> hits; 
} 

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.WRAPPER_OBJECT) 
@JsonSubTypes({ 
     @JsonSubTypes.Type(value = ImageResult.class, name = "ImageResult"), 
     @JsonSubTypes.Type(value = NewsResult.class, name = "NewsResult")}) 
public abstract class Result { 

} 

public class ImageResult extends Result { 

} 

public class NewsResult extends Result { 

} 

एक बार वर्ग (या उनके आम महाप्रकार) पैरामीटर T के रूप में पारित किया जा सकता है कि में से प्रत्येक टिप्पणी की जाती है, जैक्सन JSON में पैरामीटर T के बारे में जानकारी शामिल होंगे। ऐसे JSON को संकलन समय पर पैरामीटर T जानने के बिना deserialized किया जा सकता है।
यह Jackson documentation link पॉलिमॉर्फिक deserialization के बारे में बात करता है लेकिन इस सवाल के लिए भी उपयोगी है।

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