Jackson: How to add custom property to the JSON without modifying the POJO

后端 未结 11 1278
南方客
南方客 2020-11-27 03:10

I am developing a REST interface for my app using Jackson to serialize my POJO domain objects to JSON representation. I want to customize the serialization for some types to

11条回答
  •  轮回少年
    2020-11-27 03:46

    We can extend BeanSerializer, but with little trick.

    First, define a java class to wrapper your POJO.

    @JsonSerialize(using = MixinResultSerializer.class)
    public class MixinResult {
    
        private final Object origin;
        private final Map mixed = Maps.newHashMap();
    
        @JsonCreator
        public MixinResult(@JsonProperty("origin") Object origin) {
            this.origin = origin;
        }
    
        public void add(String key, String value) {
            this.mixed.put(key, value);
        }
    
        public Map getMixed() {
            return mixed;
        }
    
        public Object getOrigin() {
            return origin;
        }
    
    }
    

    Then,implement your custom serializer.

    public final class MixinResultSerializer extends BeanSerializer {
    
        public MixinResultSerializer() {
            super(SimpleType.construct(MixinResult.class), null, new BeanPropertyWriter[0], new BeanPropertyWriter[0]);
        }
    
        public MixinResultSerializer(BeanSerializerBase base) {
            super(base);
        }
    
        @Override
        protected void serializeFields(Object bean, JsonGenerator gen, SerializerProvider provider) throws IOException {
            if (bean instanceof MixinResult) {
                MixinResult mixin  = (MixinResult) bean;
                Object      origin = mixin.getOrigin();
    
                BeanSerializer serializer = (BeanSerializer) provider.findValueSerializer(SimpleType.construct(origin.getClass()));
    
                new MixinResultSerializer(serializer).serializeFields(origin, gen, provider);
    
                mixin.getMixed().entrySet()
                        .stream()
                        .filter(entry -> entry.getValue() != null)
                        .forEach((entry -> {
                            try {
                                gen.writeFieldName(entry.getKey());
                                gen.writeRawValue(entry.getValue());
                            } catch (IOException e) {
                                throw new RuntimeException(e);
                            }
                        }));
            } else {
                super.serializeFields(bean, gen, provider);
            }
    
        }
    
    }
    

    This way, we can handle the case that origin object using jackson annotations to custom serialize behavior.

提交回复
热议问题