如何从 Jackson 中的自定义解串器调用默认解串器

新手上路,请多包涵

我在 Jackson 的自定义反序列化器有问题。我想访问默认的序列化程序来填充我要反序列化的对象。在填充之后我会做一些自定义的事情,但首先我想用默认的 Jackson 行为反序列化对象。

这是我目前拥有的代码。

 public class UserEventDeserializer extends StdDeserializer<User> {

  private static final long serialVersionUID = 7923585097068641765L;

  public UserEventDeserializer() {
    super(User.class);
  }

  @Override
  @Transactional
  public User deserialize(JsonParser jp, DeserializationContext ctxt)
      throws IOException, JsonProcessingException {

    ObjectCodec oc = jp.getCodec();
    JsonNode node = oc.readTree(jp);
    User deserializedUser = null;
    deserializedUser = super.deserialize(jp, ctxt, new User());
    // The previous line generates an exception java.lang.UnsupportedOperationException
    // Because there is no implementation of the deserializer.
    // I want a way to access the default spring deserializer for my User class.
    // How can I do that?

    //Special logic

    return deserializedUser;
  }

}

我需要的是一种初始化默认反序列化器的方法,以便我可以在开始我的特殊逻辑之前预填充我的 POJO。

从自定义反序列化器中调用反序列化时,无论我如何构造序列化器类,该方法似乎都是从当前上下文中调用的。由于我的 POJO 中的注释。由于显而易见的原因,这会导致堆栈溢出异常。

我已经尝试初始化一个 BeanDeserializer 但这个过程非常复杂,我还没有设法找到正确的方法来做到这一点。我也尝试过重载 AnnotationIntrospector 无济于事,认为这可能会帮助我忽略 DeserializerContext 中的注释。最后它接缝我可能已经使用 JsonDeserializerBuilders 取得了一些成功,尽管这需要我做一些神奇的事情来从 Spring 获取应用程序上下文。我将不胜感激任何可以引导我找到更清晰解决方案的事情,例如如何在不阅读 JsonDeserializer 注释的情况下构建反序列化上下文。

原文由 Pablo Jomer 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 656
2 个回答

正如 StaxMan 已经建议的那样,您可以通过编写 BeanDeserializerModifier 并通过 SimpleModule 注册来做到这一点。以下示例应该有效:

 public class UserEventDeserializer extends StdDeserializer<User> implements ResolvableDeserializer
{
  private static final long serialVersionUID = 7923585097068641765L;

  private final JsonDeserializer<?> defaultDeserializer;

  public UserEventDeserializer(JsonDeserializer<?> defaultDeserializer)
  {
    super(User.class);
    this.defaultDeserializer = defaultDeserializer;
  }

  @Override public User deserialize(JsonParser jp, DeserializationContext ctxt)
      throws IOException, JsonProcessingException
  {
    User deserializedUser = (User) defaultDeserializer.deserialize(jp, ctxt);

    // Special logic

    return deserializedUser;
  }

  // for some reason you have to implement ResolvableDeserializer when modifying BeanDeserializer
  // otherwise deserializing throws JsonMappingException??
  @Override public void resolve(DeserializationContext ctxt) throws JsonMappingException
  {
    ((ResolvableDeserializer) defaultDeserializer).resolve(ctxt);
  }

  public static void main(String[] args) throws JsonParseException, JsonMappingException, IOException
  {
    SimpleModule module = new SimpleModule();
    module.setDeserializerModifier(new BeanDeserializerModifier()
    {
      @Override public JsonDeserializer<?> modifyDeserializer(DeserializationConfig config, BeanDescription beanDesc, JsonDeserializer<?> deserializer)
      {
        if (beanDesc.getBeanClass() == User.class)
          return new UserEventDeserializer(deserializer);
        return deserializer;
      }
    });

    ObjectMapper mapper = new ObjectMapper();
    mapper.registerModule(module);
    User user = mapper.readValue(new File("test.json"), User.class);
  }
}

原文由 schummar 发布,翻译遵循 CC BY-SA 3.0 许可协议

DeserializationContext 有一个 readValue() 你可以使用的方法。这应该适用于默认反序列化器和您拥有的任何自定义反序列化器。

Just be sure to call traverse() on the JsonNode level you want to read to retrieve the JsonParser to pass to readValue() .

 public class FooDeserializer extends StdDeserializer<FooBean> {

    private static final long serialVersionUID = 1L;

    public FooDeserializer() {
        this(null);
    }

    public FooDeserializer(Class<FooBean> t) {
        super(t);
    }

    @Override
    public FooBean deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException {
        JsonNode node = jp.getCodec().readTree(jp);
        FooBean foo = new FooBean();
        foo.setBar(ctxt.readValue(node.get("bar").traverse(), BarBean.class));
        return foo;
    }

}

原文由 Derek Cochran 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题