当前位置: 首页 > 知识库问答 >
问题:

Jackson自定义反序列化-无法读取JsonParser两次

东方建修
2023-03-14

我正在尝试实现一个Jackson反序列化器,以便在JSON发生变化时能够迁移JSON(例如,在重命名的字段中,我需要将现在不一致的JSON读入一致的JSON)。

一种方法是创建JsonDeserializer,将JSON作为适当的最终类读取,然后将其作为映射再次读取,以挑选更改。

但我似乎无法做到这一点,因为每次我读取或反序列化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,因为已经有一个自定义的ObjectMapper,例如,带有自定义日期反序列化器,所以当我使用MyPOJO自定义反序列化器时,我希望能够以某种方式委托反序列化,以便它使用所有以前的配置。

共有1个答案

年凯康
2023-03-14

这是我想出的:

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

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

 类似资料:
  • 我有一个定义如下的类: 另一个类包含此类对象的列表: ...并且正如注释中所指定的,我希望自定义反序列化器处理此类列表的内容。 为此,我对进行了如下扩展: 当我尝试用以下结构解析类型的Json时: ...在我自己的方法中正确调用了我,但问题是表达式只返回我(第一个令牌),因此反序列化失败。 我已经尝试把所有的东西都放在同一行(没有回车),但我也有同样的问题。这似乎是一个明显和简单的东西,但我找不到

  • 我有下面的JSON,我正试图使用Jackson API反序列化它 我基本上需要一个附件类,它有一个AttachmentFile对象列表,如下所示: 如何使用自定义反序列化器实现这一点? 谢谢

  • 情况如下:我已经设法让Jackson反序列化以下通用 作为HTTP客户端,并使用exchange

  • 问题内容: 我正在使用Flickr API 。调用该方法时,默认的JSON结果为: 我想将此响应解析为Java对象: JSON属性应按以下方式映射: 不幸的是,我无法找到一种使用Annotations做到这一点的好方法。到目前为止,我的方法是将JSON字符串读入a 并从中获取值。 但是我认为,这是有史以来最不优雅的方式。有没有简单的方法,可以使用注释还是自定义反序列化器? 这对我来说将是很明显的,

  • 我目前正在尝试使用Jackson2.8.4将自定义映射类型序列化和反序列化为JSON。我已经设法基于这个答案实现了序列化,但我正在与反序列化作斗争。下面是一个例子:

  • 我想反序列化表单中的类: 其中文本是加密的,反序列化应该在重建TestFieldEncryptedMessage实例之前取消对值的加密。 我采用的方法非常类似于:https://github.com/codesqueak/jackson-json-crypto 也就是说,我正在构建一个扩展SimpleModule的模块: 如您所见,设置了两个修饰符:EncryptedSerializerModif