2013-02-22 30 views
11

de özel bir şekilde en aşağıdaki POJO var sayalım: (De-) serialize Bean zamanında

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

Ve zamanında

, biri dışında tüm özellikleri için varsayılan seri hale getirme/deserialization istiyorum. Tipik olarak, this other question'a benzer şekilde serileştirme yaparken bir alanın kimliğini bir veritabanında değiştirmek istiyorum.

Örneğin, ben (örneğin: object1 < => "123" ve object2 < => "456"): Harici bir haritalama elde edilen bir dize tarafından o değiştirmek istiyor

  • serileştirme: okumak o ve (eğer öyleyse o dize "123" olarak serialize, object1 olan)
  • seri kaldırma değiştirin: "123" okumak geri o özgün değerini almak için bazı tabloyu sorgulamak (yani object1), bir Pojo objec yeniden o = object1 ile t.

Modüllerin bunu yapmanın bir yolu olacağını anlıyorum, ancak otomatik BeanSerializer/Deserializer'ı değiştirilmeye gerek olmayan özellikler için kullanırken bunları nasıl kullanacağımı bilmiyorum.

Birisi bir örnek (hatta var olan) veya alternatif bir yaklaşım verebilir mi?


Notlar:

  • değişiklikler derleme zamanında bilinmeyen gibi ek açıklamalar veya Katmalar kullanamaz (yani herhangi bir özellik belirlenemeyen bir şekilde değiştirilebilir olabilir).
  • This other question, işi yaptığınız gibi bir CustomSerializerFactory kullanıldığını gösterir. Ne yazık ki, resmi site it is not the recommended approach any more ve bunun yerine bu modüllerin kullanılması gerektiğini gösterir.

Düzenleme

biraz daha net olmak gerekirse, ben mesela Mixins ile aşağıdakileri yapabilirsiniz: Aşağıdaki mixin ile

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

:

abstract class PojoMixIn { 
    @JsonIgnore Object o; 
} 

Ve sonra ekleyin JSON içeriğine gerekli dize. Ama derleme zamanında bilmem gereken, değiştirilmesi gereken o alanı olduğunu bilmem gerek.

+0

> değişiklikler derleme zamanında bilinmeyen gibi ben ek açıklamaları veya Katmalar kullanamazsınız (yani herhangi özellikler> bir şekilde değişmiş olabilir (ı jakson-mapper-asl-1.9.8 kullandık) bu belirlenemez). Açıklar mısınız lütfen? Çok kafa karıştırıcı, çünkü yukarıdaki "Notlar:" başlığındaki her şey statiktir ve derleme zamanında bilinir. Pojo sınıfları (Pojo) & önceden bilinmeyen alanlar mı? –

+0

Herhangi bir sınıf yapısını üstlenmenin güvenli olmadığını mı öneriyorsunuz? Raw (untyped/simple) veri bağlamasının object JSON yapısını LinkedHashMap ve array JSON yapısını ArrayList olarak ve java ilkel sarmalayıcıları gibi ilkel JSON alanları olarak tanımlar. –

+0

@GlenBest Evet Pojo sınıfı az çok bir şey olabilir. Bir dizenin bir String ile değiştirildiği bir örnek verdim. Ama daha sonra programda, bazı String ile değiştirilmesi gereken '' '' '' '' normalde '' serileştirilmiş olabilir. – assylias

cevap

15

Sanırım @JsonSerialize ve @JsonDeserialize ihtiyacınız olan şeydir. Bu ek açıklamalar, belirli alanların serileştirilmesi/serileştirilmesi üzerinde size kontrol sağlar. This question, bunları tek bir açıklamada birleştirmenin zarif yolunu gösterir.

UPD. Bu karmaşık senaryo için BeanSerializerModifier/BeanDeserializerModifier sınıflarına bakabilirsiniz.Buradaki fikir, genel BeanSerializer/BeanDeserializer'u belirli alanlar için özel mantığınızla değiştirmek ve temel uygulamanın diğer şeyleri yapmasına izin vermektir. Bir süre sonra örnek gönderir.

UPD2. Gördüğüm gibi, yollardan biri changeProperties yöntemini kullanmak ve kendi seri hale getiricinizi atamak olabilir.

UPD3. Özel seri hale getirici çalışma örneği ile güncellendi. Deserialization benzer şekilde yapılabilir.

UPD4. Tam özel serileştirme/serileştirme ile güncellenmiş örnek.

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

Bu bilgi sadece çalışma zamanında mı kullanılabilir? Bunu özledim. – udalmik

+0

Güncellemeniz için teşekkürler - [BeanPropertyWriter] (http://fasterxml.github.com/jackson-databind/javadoc/2.1.0/com/fasterxml/jackson/databind/ser/BeanPropertyWriter.html) bir ' withSerializer 'yöntemi. Belki farklı bir versiyon kullanıyorsunuzdur? – assylias

+0

'beanPropertyWriter.assignSerializer (yeni MyCustomSerializer());' hile yaptı. – assylias