使用Jackson对JSONP进行初始化

9jyewag0  于 4个月前  发布在  其他
关注(0)|答案(3)|浏览(57)

由于某些原因,Jackson2.3.0无法解析JSONP响应。

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

字符串
我已经在没有回调的情况下完成了重命名过程。
我尝试过使用包含@JSONP注解的JacksonJAX-RS包,但这似乎只在序列化时使用。

oogrdqng

oogrdqng1#

下面是我使用ReaderInterceptor提出的解决方案的一个精简版,我使用Jersey 2.x和Jackson与一个只输出JSONP的Web服务交互。

public class CallbackStripInterceptor implements ReaderInterceptor {

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

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

    int howMany = callbackBytes.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不会对没有实体主体的响应运行拦截器)。

jv4diomz

jv4diomz2#

最后,我已经能够删除JSONP响应的回调部分。
首先,Jackson能够解析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。
我还能够使用json.org库中的JSONTokener对给定的JSONP String实现相同的结果:

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

y4ekin9u

y4ekin9u3#

如果你使用伪装,你可以使用下面的解决方案。

import java.io.IOException;

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;

import feign.InvocationContext;
import feign.Response;
import feign.ResponseInterceptor;
import lombok.AccessLevel;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@RequiredArgsConstructor(access = AccessLevel.PUBLIC)
public class JsonpResponseInterceptor implements ResponseInterceptor {

    private final String identifier;

    @Override
    public Object aroundDecode(InvocationContext invocationContext) throws IOException {
        String resp = IOUtils.toString(invocationContext.response().body().asInputStream(),
                invocationContext.response().charset());
        LOGGER.debug("response is :"+resp);
        if (resp.startsWith(identifier)) {
            String substring = StringUtils.substringBetween(resp, "(", ")");
            Response modifiedResponse = Response.builder().body(substring, invocationContext.response().charset())
                    .headers(invocationContext.response().headers())
                    .protocolVersion(invocationContext.response().protocolVersion())
                    .reason(invocationContext.response().reason()).status(invocationContext.response().status())
                    .request(invocationContext.response().request()).build();
            return invocationContext.decoder().decode(modifiedResponse, invocationContext.returnType());
        } else {
            return invocationContext.proceed();
        }
    }
}

字符串

相关问题