2013-11-19 2 views
2

По какой-то причине Jackson 2.3.0 не может разобрать ответ JSONP.Deserialize JSONP с Jackson

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

У меня процесс десериализации для работы без обратного вызова.

Я пробовал с пакетом Jackson JAX-RS, который содержит аннотацию @JSONP, но это, похоже, используется только при сериализации.

+0

ну, я попробовал с пользовательским десериализатором, но исключение бросается до того, как сделан вызов метода десериализации. – Eldelshell

ответ

2

Наконец-то я смог удалить часть обратного вызова ответа JSONP.

Во-первых, Джексон может разбирать JSON, даже когда он заканчивается скобкой. Таким образом, просто удаляя my_json_callback( из ответа достаточно.

Поскольку я использую HTTP Client Apache, это устраняет проблему:

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

Идея не имея преобразовать читателя в строку, а затем разбор этой строки после удаления обратного вызова часть.

Я также был в состоянии выполнить те же результаты, используя JSONTokener из json.org библиотеки для данной JSONP строки:

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

Вот версия обрезаны-для-пространства решения я пришел с использованием ReaderInterceptor. Я использую Jersey 2.x совместно с Jackson для взаимодействия с веб-сервисом, который выводит только JSONP.

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(); 

С помощью этого клиента, все ответы с объектом будут проходить через этот перехватчик (Джерси не работают перехватчики на ответы без тел сущностей).

Смежные вопросы