2013-02-22 12 views
11

पर एक कस्टम तरह से की कल्पना मैं निम्नलिखित POJO करते हैं:(De-) को क्रमानुसार बीन क्रम

class Pojo { 
    String s; 
    Object o; 
    Map<String, String> m; 
} 

और रनटाइम पर, मैं एक को छोड़कर सभी गुण के लिए डिफ़ॉल्ट क्रमांकन/deserialization चाहते हैं। आम तौर पर, मैं this other question के समान क्रमबद्ध होने पर डेटाबेस में अपनी आईडी द्वारा किसी डेटाबेस को प्रतिस्थापित करना चाहता हूं।

उदाहरण के लिए, मैं एक स्ट्रिंग एक बाहरी मानचित्रण से प्राप्त द्वारा o को बदलने के लिए (उदाहरण के लिए: object1 < => "123" और object2 < => "456"): चाहते

  • क्रमबद्धता: पढ़ा o और की जगह (इसलिए यदि oobject1 है, स्ट्रिंग "123" के रूप में क्रमानुसार)
  • अक्रमांकन: "123", पढ़ने के कुछ तालिका क्वेरी o के मूल मूल्य वापस पाने के लिए (यानी object1), एक Pojo ओर्ब पुन: o = object1 के साथ टी।

मैं समझता हूं कि मॉड्यूल ऐसा करने का एक तरीका होगा, लेकिन मुझे यह सुनिश्चित नहीं है कि स्वचालित बीनसेरियलाइज़र/Deserializer को उन गुणों के लिए कैसे उपयोग किया जाए जिन्हें बदलने की आवश्यकता नहीं है।

क्या कोई कोई उदाहरण (यहां तक ​​कि प्रदूषित) या वैकल्पिक दृष्टिकोण दे सकता है?


नोट्स:

  • मैं एनोटेशन या mixins उपयोग नहीं कर सकते के रूप में परिवर्तन संकलन समय पर अज्ञात हों (जैसे कि किसी भी गुण एक तरीका है कि निर्धारण नहीं है में बदला जा सकता है)।
  • This other question एक कस्टमसेरियलाइज़र फैक्टरी का उपयोग करने के लिए अंक, जो नौकरी करने लगता है। दुर्भाग्यवश, आधिकारिक साइट इंगित करती है कि it is not the recommended approach any more और इसके बजाय मॉड्यूल का उपयोग किया जाना चाहिए।

संपादित

एक छोटे से स्पष्ट होने के लिए, मैं उदाहरण के लिए mixins साथ निम्न कर सकते हैं:

ObjectMapper mapper = new ObjectMapper(MongoBsonFactory.createFactory()); 
mapper.addMixInAnnotations(Pojo.class, PojoMixIn.class); 

ObjectReader reader = mapper.reader(Pojo.class); 
DBEncoder dbEncoder = DefaultDBEncoder.FACTORY.create(); 
OutputBuffer buffer = new BasicOutputBuffer(); 
dbEncoder.writeObject(buffer, o); 
निम्नलिखित Mixin के साथ

:

abstract class PojoMixIn { 
    @JsonIgnore Object o; 
} 

और फिर जोड़ें जेएसओएन सामग्री के लिए आवश्यक स्ट्रिंग। लेकिन मुझे संकलन समय पर जानना होगा कि यह o फ़ील्ड है जिसे प्रतिस्थापित करने की आवश्यकता है, जो मैं नहीं करता हूं।

+0

> मैं एनोटेशन या mixins उपयोग नहीं कर सकते के रूप में परिवर्तन संकलन समय पर अज्ञात हैं (यानी किसी भी गुण हो> एक तरह से बदल सकता है (मैं jakson-नक्शाकार-ASL-1.9.8 का इस्तेमाल किया है) यह निर्धारित नहीं है)। क्या आप स्पष्टीकरण दे सकते हैं? बहुत उलझन में, क्योंकि उपरोक्त सब कुछ "नोट्स:" शीर्षक स्थिर है और संकलन समय पर जाना जाता है। क्या कक्षाएं (पोजो) और पोजो के क्षेत्र अग्रिम में ज्ञात नहीं हैं? –

+0

क्या आप सुझाव दे रहे हैं कि किसी भी वर्ग संरचना को मानना ​​सुरक्षित नहीं है? कच्चे (untyped/simple) डेटा बाइंडिंग deserialises ऑब्जेक्ट JSON संरचना LinkedHashMap <स्ट्रिंग, ऑब्जेक्ट>, और सरणी JSON संरचना के रूप में ArrayList , और प्राचीन जेएसओएन फ़ील्ड जावा आदिम रैपर के रूप में। –

+0

@GlenBest हां पोजो वर्ग कम या ज्यादा कुछ भी हो सकता है। मैंने एक उदाहरण दिया जहां 'ओ' को स्ट्रिंग द्वारा प्रतिस्थापित किया गया है। लेकिन बाद में कार्यक्रम में, यह 'एम' हो सकता है जिसे कुछ स्ट्रिंग और 'ओ' क्रमबद्ध "सामान्य" द्वारा प्रतिस्थापित किया जाना चाहिए। – assylias

उत्तर

15

मुझे लगता है कि @JsonSerialize और @JsonDeserialize आपको जो चाहिए वह है। ये एनोटेशन आपको विशेष क्षेत्रों के क्रमिकरण/deserialization पर नियंत्रण देते हैं। This question उन्हें एक एनोटेशन में गठबंधन करने के लिए सुरुचिपूर्ण तरीका दिखाता है।

यूपीडी। इस जटिल परिदृश्य के लिए आप BeanSerializerModifier/BeanDeserializerModifier कक्षाओं पर एक नज़र डाल सकते हैं।विचार सामान्य क्षेत्रों के लिए अपने कस्टम तर्क के साथ सामान्य BeanSerializer/BeanDeserializer को संशोधित करना और अन्य सामग्री को करने के लिए बुनियादी कार्यान्वयन देना है। कुछ समय बाद एक उदाहरण पोस्ट करेंगे।

UPD2। जैसा कि मैंने देखा, एक तरीका changeProperties विधि का उपयोग करने और अपना स्वयं का धारावाहिक असाइन करने का तरीका हो सकता है।

UPD3। कस्टम धारावाहिक के कामकाजी उदाहरण के साथ अद्यतन किया गया। Deserialization इसी तरह से किया जा सकता है।

UPD4। पूर्ण कस्टम क्रमिकरण/deserialization के साथ अद्यतन उदाहरण।

public class TestBeanSerializationModifiers { 

    static final String PropertyName = "customProperty"; 
    static final String CustomValue = "customValue"; 
    static final String BaseValue = "baseValue"; 

    // Custom serialization 

    static class CustomSerializer extends JsonSerializer<Object> { 
     @Override 
     public void serialize(Object value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException { 
      String customValue = CustomValue; // someService.getCustomValue(value); 
      jgen.writeString(customValue); 
     } 
    } 

    static class MyBeanSerializerModifier extends BeanSerializerModifier { 
     @Override 
     public List<BeanPropertyWriter> changeProperties(SerializationConfig config, BasicBeanDescription beanDesc, List<BeanPropertyWriter> beanProperties) { 
      for (int i = 0; i < beanProperties.size(); i++) { 
       BeanPropertyWriter beanPropertyWriter = beanProperties.get(i); 
       if (PropertyName.equals(beanPropertyWriter.getName())) { 
        beanProperties.set(i, beanPropertyWriter.withSerializer(new CustomSerializer())); 
       } 
      } 
      return beanProperties; 
     } 
    } 

    // Custom deserialization 

    static class CustomDeserializer extends JsonDeserializer<Object> { 
     @Override 
     public Object deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException { 
      // serialized value, 'customValue' 
      String serializedValue = jp.getText(); 
      String baseValue = BaseValue; // someService.restoreOldValue(serializedValue); 
      return baseValue; 
     } 
    } 

    static class MyBeanDeserializerModifier extends BeanDeserializerModifier { 
     @Override 
     public BeanDeserializerBuilder updateBuilder(DeserializationConfig config, BasicBeanDescription beanDesc, BeanDeserializerBuilder builder) { 
      Iterator<SettableBeanProperty> beanPropertyIterator = builder.getProperties(); 
      while (beanPropertyIterator.hasNext()) { 
       SettableBeanProperty settableBeanProperty = beanPropertyIterator.next(); 
       if (PropertyName.equals(settableBeanProperty.getName())) { 
        SettableBeanProperty newSettableBeanProperty = settableBeanProperty.withValueDeserializer(new CustomDeserializer()); 
        builder.addOrReplaceProperty(newSettableBeanProperty, true); 
        break; 
       } 
      } 
      return builder; 
     } 
    } 

    static class Model { 

     private String customProperty = BaseValue; 
     private String[] someArray = new String[]{"one", "two"}; 

     public String getCustomProperty() { 
      return customProperty; 
     } 

     public void setCustomProperty(String customProperty) { 
      this.customProperty = customProperty; 
     } 

     public String[] getSomeArray() { 
      return someArray; 
     } 

     public void setSomeArray(String[] someArray) { 
      this.someArray = someArray; 
     } 
    } 

    public static void main(String[] args) { 
     SerializerFactory serializerFactory = BeanSerializerFactory 
       .instance 
       .withSerializerModifier(new MyBeanSerializerModifier()); 

     DeserializerFactory deserializerFactory = BeanDeserializerFactory 
       .instance 
       .withDeserializerModifier(new MyBeanDeserializerModifier()); 

     ObjectMapper objectMapper = new ObjectMapper(); 
     objectMapper.setSerializerFactory(serializerFactory); 
     objectMapper.setDeserializerProvider(new StdDeserializerProvider(deserializerFactory)); 

     try { 
      final String fileName = "test-serialization.json"; 
      // Store, "customValue" -> json 
      objectMapper.writeValue(new File(fileName), new Model()); 
      // Restore, "baseValue" -> model 
      Model model = objectMapper.readValue(new File(fileName), Model.class); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 
} 
+0

यह जानकारी केवल रनटाइम पर उपलब्ध है? याद किया कि। – udalmik

+0

आपके अपडेट के लिए धन्यवाद - [बीनप्रॉपर्टीवाइटर] (http://fasterxml.github.com/jackson-databind/javadoc/2.1.0/com/fasterxml/jackson/databind/ser/BeanPropertyWriter.html) में ' Serializer' विधि के साथ। शायद आप एक अलग संस्करण का उपयोग कर रहे हैं? – assylias

+0

'beanPropertyWriter.assignSerializer (नया MyCustomSerializer()); चाल चल रही थी। – assylias

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