(De-)在运行时以自定义方式序列化Bean

我们假设我有以下POJO:

class Pojo { String s; Object o; Map m; } 

在运行时,我想要除了一个属性之外的所有属性的默认序列化/反序列化。 通常,我想在序列化时用数据库中的ID替换字段,类似于其他问题 。

例如,我想用从外部映射获得的字符串替换o (例如: object1 “123”和object2 “456”):

  • 序列化:读取o和替换(如果oobject1 ,则序列化为字符串“123”)
  • 反序列化:读取“123”,查询某些表以获取o的原始值(即object1 ),用o = object1重新创建一个Pojo对象。

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

有人可以给出一个例子(甚至做作)或另类方法吗?


笔记:

  • 我不能使用注释或Mixins,因为在编译时未知更改(即任何属性可能以不可确定的方式更改)。
  • 另一个问题指向使用CustomSerializerFactory,它似乎可以完成这项工作。 不幸的是,官方网站表明它不再是推荐的方法 ,而是应该使用模块。

编辑

为了更清楚一点,我可以使用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; } 

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

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

UPD。 对于这个复杂的场景,您可以查看BeanSerializerModifier/BeanDeserializerModifier类。 我们的想法是使用您的特定字段的自定义逻辑修改常规BeanSerializer/BeanDeserializer ,并让基本实现执行其他操作。 稍后会发布一个例子。

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

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

UPD4。 更新了完整自定义序列化/反序列化的示例。 (我使用过jakson-mapper-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 { @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 changeProperties(SerializationConfig config, BasicBeanDescription beanDesc, List 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 { @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 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(); } } }