【问题标题】:Jackson custom deserialization - can't read JsonParser twice杰克逊自定义反序列化 - 无法读取 JsonParser 两次
【发布时间】:2018-04-02 00:05:14
【问题描述】:

我正在尝试实现一个 Jackson Deserializer,以便在 JSON 发生变化时迁移它们(例如,重命名的字段,我需要将现在不一致的 JSON 读入一致的 JSON)。

这样做的一种方法是创建一个 JsonDeserializer,将 JSON 作为正确的最终类读取,然后将其作为 MAP 再次读取,以挑选更改。

但我似乎不能这样做,因为每次我读取或反序列化 JSON 时,支持 Stream 都会关闭。

class CustomDeserializer extends StdDeserializer<MyPOJO> implements ResolvableDeserializer{

    private final JsonDeserializer<?> deserializer;
    private final ObjectMapper mapper;

    public CustomDeserializer(JsonDeserializer<?> deserializer, ObjectMapper mapper) {
        super(MyPOJO.class);
        this.deserializer = deserializer;
        this.mapper = mapper;
    }

    @Override
    public MyPOJO deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException {
        MyPOJO deserialized = (MyPOJO) deserializer.deserialize(jp, ctxt);
        // Custom migration would go here...
        return deserialized;
    }

    @Override
    public void resolve(DeserializationContext ctxt) throws JsonMappingException {
        ((ResolvableDeserializer) deserializer).resolve(ctxt);
    }
}

我正在避免创建新的 ObjectMapper,因为已经有一个自定义的 ObjectMapper,例如,带有自定义 Date 反序列化器,所以当我使用 MyPOJO 自定义反序列化器时,我希望能够以某种方式委托反序列化,因此它使用之前的所有配置。

【问题讨论】:

    标签: java json serialization


    【解决方案1】:

    这是我想出的:

    @Autowired
        public Serializer(List<IDeserializer> deserializers) {
            SimpleModule module = new SimpleModule("name");
            registerDeserializers(module, deserializers);
            mapper.registerModule(module);
            mapper.configure(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS, true);
            mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
            mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd"));
        }
    
        private void registerDeserializers(SimpleModule module, List<IDeserializer> deserializers) {
            if (CollectionUtils.isNotEmpty(deserializers)) {
                final Map<Class<?>, IDeserializer> deserializerRegistryMap = toMap(deserializers);
                module.setDeserializerModifier(new BeanDeserializerModifier() {
                    @Override
                    public JsonDeserializer<?> modifyDeserializer(DeserializationConfig config, BeanDescription beanDesc, JsonDeserializer<?> deserializer) {
                        if (deserializerRegistryMap.containsKey(beanDesc.getBeanClass())){
                            return deserializerRegistryMap.get(beanDesc.getBeanClass()).getDeserializer(mapper);
                        }
                        return super.modifyDeserializer(config, beanDesc, deserializer);
                    }
                });
            }
        }
    
    
    @Component
    public class MigrationDeserializer {
    
        @Autowired
        private MigratorRegistry migratorRegistry;
    
        public <T> JsonDeserializer<T> createDeserializer(final ObjectMapper mapper, final Class<T> returnType, final Class<? extends SerializedObjectsHistory<T>> historyType){
           return new StdDeserializer<T>(returnType){
    
               @Override
               public T deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
                   SerializedObjectsHistory<T> history = mapper.readValue(p, historyType);
                   return migratorRegistry.migrate(history, returnType);
               }
           };
        }
    }
    

    在序列化程序上,我将我的 POJO 反序列化为“HistoryPOJO”,这与我的 POJO 基本相同,但包含所有字段,甚至包括删除/重命名的字段。

    然后我将其转换为当前版本。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-01-31
      • 1970-01-01
      • 1970-01-01
      • 2013-08-11
      • 2019-08-04
      • 2017-01-30
      相关资源
      最近更新 更多