杰克逊自定义反序列化 - 无法读取JsonParser两次

时间:2017-10-20 18:49:23

标签: java json serialization

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

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

我似乎无法这样做,因为每次我读取或反序列化JSON时,后备流都会关闭。

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,因为已经有一个定制的,有自定义的日期反序列化器,所以当我使用MyPOJO自定义反序列化器时,我希望能够以某种方式委托反序列化,以便它使用以前的所有配置。

1 个答案:

答案 0 :(得分:0)

这就是我提出的:

@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基本相同,但包含所有字段,甚至删除/重命名的字段。

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