2013-02-22 64 views
11

定制的方式让我们想象一下,我有以下POJO:(去)序列化豆在运行时

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

并在运行时,我想,除了为一个所有属性默认序列化/反序列化。通常,我想在序列化时用数据库中的ID替换字段,类似于this other question

例如,我想通过从外部映射而获得的字符串来替换o(例如:object1 < => “123” 和object2 < => “456”):

  • 序列:读o和替换(所以如果oobject1,序列化为字符串“123”)
  • 反序列化:读“123”,查询一些表来获得o原始值回(即object1),重新建立一个Pojo objec t与o = object1

我明白,模块将是一种方法来做到这一点,但我不知道如何使用它们,同时保持自动BeanSerializer/Deserializer的属性,不需要改变。

有人可以举一个例子(甚至设计)或另一种方法?


注:

  • 我不能使用注释或混入作为变化是在编译时未知(即任何属性可能的方式是不确定的改变)。
  • This other question指向使用CustomSerializerFactory,这似乎做了这项工作。不幸的是,官方网站表明应该使用it is not the recommended approach any more和那个模块。

编辑

为了更清晰一点,我可以做混入下面的例子:

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

然后添加JSON内容所需的字符串。但在编译时我需要知道它是o字段需要被替换,我不这样做。

+0

>我不能使用注释或混入作为变化是在编译时未知(即任何属性可能>的方式改变这是不可确定的)。你能澄清一下吗?非常困惑,因为“注释:”上面的所有内容都是静态的,并且在编译时已知。班级(Pojo)和Pojo领域事先不知道? – 2013-02-26 11:10:59

+0

您是否建议假设任何班级结构并不安全? Raw(无类型/简单)数据绑定将对象JSON结构反序列化为LinkedHashMap 和数组JSON结构作为ArrayList ,并将原始JSON字段作为java原始包装。 – 2013-02-26 11:30:08

+0

@GlenBest是的,Pojo类可以是或多或少的东西。我举了一个例子,其中'o'被一个String替换。但后来在程序中,它可能是'm',它需要被一些字符串替代,而'o'通常被“序列化”。 – assylias 2013-02-26 15:59:38

回答

15

我认为@JsonSerialize@JsonDeserialize是你需要的。这些注释可以控制特定字段的序列化/反序列化。 This question显示了将它们组合成一个注释的优雅方式。

UPD。对于这个复杂的场景,你可以看看BeanSerializerModifier/BeanDeserializerModifier类。这个想法是修改一般BeanSerializer/BeanDeserializer与您的自定义逻辑的特定领域,并让基本实施做其他的东西。稍后会发布一个例子。

UPD2。正如我所看到的,其中一种方法可能是使用changeProperties方法并分配您自己的序列化程序。

UPD3。更新了自定义序列化器的工作示例。反序列化可以用类似的方式完成。

UPD4。全自定义序列化/反序列化的更新示例。 (我已经使用jakson映射器-ASL-1.9.8

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 2013-02-24 14:02:02

+0

感谢您的更新 - [BeanPropertyWriter](http://fasterxml.github.com/jackson-databind/javadoc/2.1.0/com/fasterxml/jackson/databind/ser/BeanPropertyWriter.html)没有' withSerializer'方法。也许你正在使用不同的版本? – assylias 2013-02-26 16:12:28

+0

'beanPropertyWriter.assignSerializer(new MyCustomSerializer());'做了诀窍。 – assylias 2013-02-26 16:15:20