用杰克逊反序列化JSONP

时间:2013-11-19 10:32:35

标签: java jsonp jackson

由于某些原因,Jackson 2.3.0无法解析JSONP响应。

com.fasterxml.jackson.core.JsonParseException: Unrecognized token 'my_json_callback':

我已经让反序列化过程在没有回调的情况下工作。

我尝试过使用包含@JSONP注释的Jackson JAX-RS软件包,但这似乎仅在序列化时使用。

2 个答案:

答案 0 :(得分:3)

这是我使用ReaderInterceptor提出的解决方案的空间版本。我将Jersey 2.x与Jackson结合使用,以便与仅输出JSONP的Web服务进行交互。

public class CallbackStripInterceptor implements ReaderInterceptor {

    private final static byte[] bytes = "callback(".getBytes();

    @Override
    public Object aroundReadFrom(ReaderInterceptorContext context) throws IOException, WebApplicationException {

    int howMany = bytes.length;

    InputStream x = context.getInputStream();

    if( !(x.available() >= howMany) ) {
        return context.proceed();
    }

    x.mark( howMany );
    byte[] preamble = new byte[ howMany ];
    x.read( preamble );

    // In case the first part of our entity doesn't have the callback String, reset the stream so downstream exploiters get the full entity.
    if( !Arrays.equals( preamble, callbackBytes ) ) {
        x.reset();
    } 

    return context.proceed();
}

像这样使用:

Client c = ClientBuilder.newBuilder()
    .register( new CallbackStripInterceptor() )
    .build();

使用此客户端,所有与实体的响应都将通过此拦截器(Jersey不会在没有实体主体的响应中运行拦截器。)

答案 1 :(得分:2)

最后,我已经能够删除JSONP响应的回调部分。

首先,杰克逊能够解析JSON,即使它以括号结尾。因此,只需从响应中删除my_json_callback(即可。

由于我使用的是Apache的HTTP客户端,因此解决了这个问题:

String callback = "my_json_callback(";
InputStreamReader r = new InputStreamReader(response.getEntity().getContent());
r.skip(callback.length());
return mapper.readValue(r, MyObject.class);

这个想法不是必须将Reader转换为String,然后在删除回调部分后解析该String。

对于给定的JSONP字符串,我还可以使用JSONTokener库中的json.org来完成相同的结果:

JSONTokener t = new JSONTokener(json);
t.nextValue(); // skip the callback
return mapper.readValue(t.nextValue().toString(), MyObject.class);