(De-)Serialize Bean in a custom way at runtime

后端 未结 1 1356
猫巷女王i
猫巷女王i 2021-02-01 09:07

Let\'s imagine I have the following POJO:

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

And at runtime, I want de

1条回答
  •  -上瘾入骨i
    2021-02-01 09:10

    I think @JsonSerialize and @JsonDeserialize is what you need. These annotations give you control on the serialization/deserialization of particular fields. This question shows elegant way to combine them into one annotation.

    UPD. For this complex scenario you could take a look at BeanSerializerModifier/BeanDeserializerModifier classes. The idea is to modify general BeanSerializer/BeanDeserializer with your custom logic for particular fields and let basic implementation to do other stuff. Will post an example some time later.

    UPD2. As I see, one of the way could be to use changeProperties method and assign your own serializer.

    UPD3. Updated with working example of custom serializer. Deserialization could be done in similar way.

    UPD4. Updated example with full custom serialization/deserialization. (I have used 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();
            }
        }
    }
    
        

    0 讨论(0)
    提交回复
    热议问题