拦截杰克逊的反序列化

Edd*_*die 6 java jackson

我想挂钩杰克逊的反序列化,以选择反序列化不同于提供的JSON文档的JSON文档.这似乎是一个非常奇怪的用例,所以让我解释一下.

我正在使用Amazon SQS Extended客户端在S3上放置对于SQS而言太大的消息,并通过SQS显示如下所示的消息

["com.amazon.sqs.javamessaging.MessageS3Pointer",{"s3BucketName":"my-bucket","s3Key":"f5a0fa29-7f9c-4852-8bbb-53697799efe2"}]
Run Code Online (Sandbox Code Playgroud)

一个弹性beanstalk工作者正在监听另一端,这意味着这些消息被POST到我的应用程序维护的Jersey端点.由于这些消息是POST而不是使用SQS receiveMessage调用,因此扩展客户端不会从S3本身获取消息.

我认为制作一个自定义的自定义将是非常聪明的JsonDeserializer,看看它是否是一个S3指针,下载该文件,并反序列化它.否则,只需反序列化提供的消息.然而,这并不像我希望的那样顺利.

这是我到目前为止:

public class SQSS3Deserializer<T> extends JsonDeserializer<T> {
    private static final String s3PointerHeader = "com.amazon.sqs.javamessaging.MessageS3Pointer";
    private Class<T> type;
    private ObjectMapper mapper = new ObjectMapper();

    public SQSS3Deserializer() {
        super();

        type = getParameterizedTypeArgument();
    }

    @Override
    public T deserialize(JsonParser jp, DeserializationContext dc) throws IOException, JsonProcessingException {
        if (jp.isExpectedStartArrayToken()) {
            jp.nextToken();
            if (s3PointerHeader.equals(jp.getValueAsString())) {
                jp.nextToken();
                S3Pointer p = jp.readValueAs(S3Pointer.class);
                return mapper.readValue(S3Utils.getInputStream(p.s3BucketName, p.s3Key), type);
            }
        }

        return jp.readValueAs(type);
    }

    @SuppressWarnings("unchecked")
    protected Class<T> getParameterizedTypeArgument() {
        return (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
    }

    static private class S3Pointer {
        public String s3BucketName;
        public String s3Key;
    }

}
Run Code Online (Sandbox Code Playgroud)

对于每个要反序列化的POJO,我必须使用正确的泛型特化创建一个空子类,例如:

public class POJOS3Deserializer extends SQSS3Deserializer<POJO> {}
Run Code Online (Sandbox Code Playgroud)

我还需要将JsonDeserializer注释添加到类中

@JsonDeserialize(using=POJOS3Deserializer.class)
public class POJO { ... }
Run Code Online (Sandbox Code Playgroud)

但是,这样做会导致堆栈溢出错误,因为它会在调用时不断重新输入我的反序列化器,JsonParser.readValueAs()因为readValueAs会查看JsonDeserialize注释.

所以,我有两个问题:

  1. 我如何改变这一点以保持这种相当通用,并且仍然让杰克逊做大部分解析的重要工作,同时避免递归调用?
  2. 有没有办法消除从每个POJO派生SQSS3Deserializer的需要我想以这种方式反序列化?

谢谢