2012-01-20 10 views
7

तक पहुंच प्राप्त करना मैं जैक्सन के लिए एक कस्टम deserializer लिखने की कोशिश कर रहा हूँ और मैं इसे सामान्य (सामान्य "जेनेरिक" के रूप में नहीं, किसी भी प्रकार पर काम करने की भावना में जेनेरिक बनाना चाहता हूं)।कस्टम जैक्सन Deserializer वर्तमान फील्ड कक्षा

हालांकि मुझे यह पता लगाना प्रतीत नहीं होता कि क्षेत्र के प्रकार को हरे रंग के तरीके से कैसे संभाला जाए।

जैसे, मैं निम्नलिखित की तरह कुछ करने के लिए देख रहा हूँ:

@Override 
public MyObject deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException { 

     Class c = <get type of current field> 
     // do something with that type 
     return new SubclassOfC(somedata based on c); 
} 

यह विशेष रूप से वर्तमान क्षेत्र के प्रकार प्राप्त बात यह है कि मैं के साथ संघर्ष किया है।

संपादित करें: यह जावा क्षेत्र मैं में दिलचस्पी के प्रकार है

+0

"वर्तमान क्षेत्र के प्रकार के" करके आप JSON मूल्य (वस्तु, सरणी, स्ट्रिंग, पूर्णांक, आदि के प्रकार के क्या मतलब है)? या 'MyObject' में एक ही नाम वाले जावा फ़ील्ड का प्रकार जिसे आप JSON मान मैप कर रहे हैं? –

+0

बाद वाला, जावा फ़ील्ड का प्रकार। – monkjack

उत्तर

2

मैंने ऑब्जेक्टमैपर को Deserializers के कार्यान्वयन को जोड़कर अपनी विशेष समस्या हल कर दी है। उदाहरण के लिए

Deserializers d = new Deserializers.Base() { 

    @Override 
    public JsonDeserializer<?> findEnumDeserializer(Class<?> type, DeserializationConfig config, BeanDescription beanDesc, BeanProperty property) 
        throws JsonMappingException { 
       if (property.getType().getContentType() != null) 
        return new EnumDeserializer(property.getType().getContentType().getRawClass()); 
       return new EnumDeserializer(property.getType().getRawClass()); 
      } 

     }; 
     mapper.setDeserializerProvider(mapper.getDeserializerProvider().withAdditionalDeserializers(d)); 

यह मेरा कस्टम EnumDeserializer प्रत्येक अलग Enum प्रकार के लिए instantiated वापस आ जाएगी।

+0

ने मुझे कुछ समय बचाया लेकिन आईएमओ अपने enum deserializer का उपयोग नहीं करते हैं। अपने आप को लिखने के लिए सरल, सभी प्रकार के भयानक बहिष्कार। – MikePatel

+0

मैं सिर्फ यह जोड़ना चाहता था कि इस Deserializers को नए जैक्सन एपीआई पर ओह इतना अपवित्र है। उदाहरण के माध्यम से प्रदान किया गया उदाहरण: https://gist.github.com/patelm5/9268866 – MikePatel

0

मोटे तौर पर, और अपवाद को पकड़ने और त्रुटि जाँच के बिना ...

JsonToken tok = jp.nextValue(); 

Field field = findField(jp.getCurrentName()); 

Class<?> fc = field.getType(); 

if(fc == int.class) { 
    field.setInt(this, jp.getIntValue()); 
} // handle all the primitive types and String in the same way, then... 
} ... else if(tok == JsonToken.START_ARRAY) { 
    if(fc.isArray()) { 
     // Load into an array 
    } else if(Collection.class.isAssignableFrom(fc)) { 
     // Load into a collection 
    } else { 
     // throw 
    } 
} else if(tok == JsonToken.START_OBJECT) { 
    // Recursively create that object from the JSON stream 
} 

... और tok जब तक पाश। END_OBJECT है नाम से वर्तमान वर्ग के एक खोजने के लिए:

Field findField(String name) { 
    for(Class<?> c = getClass(); c != null; c = c.getSuperclass()) { 
     for(Field field : c.getDeclaredFields()) { 
      if(field.getName().equals(name)) { 
       return field; 
      } 
     } 
    } 
} 
+0

नहीं मिलेगा फ़ील्ड deserializer की कक्षा के अंदर देखो, न कि वर्ग जो deserializer unmarshall के लिए बनाया गया था? – monkjack

3

आप नहीं करते हैं - deserializers, प्रकार के आधार पर पंजीकृत हैं तो आप को पता है यह deserialize की उम्मीद है किस प्रकार deserializer के निर्माण के लिए की जरूरत है।

यदि आप एक सामान्य deserializer पंजीकृत करना चाहते हैं, तो आप ContextualDeserializer लागू करके चीजों को और अधिक गतिशील बना सकते हैं। इसकी createContextual() विधि BeanProperty तर्क के साथ बुलाया जाता है, और आप संपत्ति के नाम की तरह चीजें देख सकते हैं (जो रूट मानों के मामले में शून्य हो सकती है, जिन्हें किसी संपत्ति द्वारा संदर्भित नहीं किया जाता है) और टाइप करें (जो घोषित प्रकार है)। यह विधि तब एक नया उदाहरण लौटा सकती है (मूल deserializer को संशोधित न करें, क्योंकि यह सभी गुणों द्वारा साझा की जाती है), जो आपको आवश्यक सभी अतिरिक्त जानकारी के साथ कॉन्फ़िगर किया गया है।

+0

यह एक अच्छा जवाब था, दुर्भाग्य से ऐसा लगता है कि यदि आप कक्षा एनम के साथ एक Deserializer पंजीकृत करते हैं, तो जैक्सन आपकी कस्टम कक्षा से बात नहीं करता है, लेकिन यह enum deserializer में बनाया गया है। इसका मतलब है कि मुझे अपनी संस्थाओं में हर enum प्रकार के साथ अपने cusom enum deserializer रजिस्टर करना होगा। – monkjack

+2

दाएं, deserializers पंजीकृत करते समय, वे उस विशिष्ट प्रकार पर लागू होते हैं जिसके लिए आप इसे पंजीकृत करते हैं।यदि आप सभी enum प्रकारों को संभालने के लिए कुछ बनाना चाहते हैं, तो आपको 'Deserializers' को लागू करने की आवश्यकता होगी, इसे पंजीकृत करें: इसके 'findEnumDeserializer()' कॉलबैक को हर बार एक एनम प्रकार के लिए एक नया deserializer की आवश्यकता होती है। – StaxMan

+0

मैं कक्षा के लिए एक बीनप्रोपर्टी ऑब्जेक्ट कैसे बना सकता हूं जिसे मैं deserialize करना चाहता हूं? –

0

मैंने इसे इस तरह हल किया।

, वर्तमान क्षेत्र जावा प्रकार प्राप्त करें ...

@Override 
public Enum deserialize(JsonParser jsonparser, DeserializationContext context) throws IOException, JsonProcessingException { 
    System.out.println("EnumDeserializer ...."); 
    Field field = findField(jsonparser.getCurrentName(), jsonparser.getCurrentValue().getClass()); 
    Class<?> javaType = field.getType(); 
    return null; 
} 

public Field findField(String name, Class<?> c) { 
    for (; c != null; c = c.getSuperclass()) { 
     for (Field field : c.getDeclaredFields()) { 
      if (Modifier.isStatic(field.getModifiers())) { 
       continue; 
      } 
      if (field.getName().equals(name)) { 
       return field; 
      } 
     } 
    } 
    return null; 
} 

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