Parse Api ответ не полностью "JSON" с переоборудованием и Моши
Я нашел и API, что я хочу попробовать, но ответ не "полный JSON", поэтому, когда я получаю ответ, я получаю ошибку синтаксического анализатора.
Как обычно, я использую модернизацию, поэтому более или менее важная часть выглядит так:
val retrofit = Retrofit.Builder()
.baseUrl(AwsomeAPIConstants.HOST)
.addConverterFactory(MoshiConverterFactory.create())
.build()
awsomeApi = retrofit.create(AwsomeaApiService::class.java)
Как я уже сказал, все ответы API похожи на: <sentence> = {<json>}
очевидно, что MoshiConverter не может разобрать его.
Некоторые примеры ответа:
info={'timestamp':1292608331,'error':0}
info={'status':1,'error':0}
search={'error':1}
Есть ли способ разобрать это?
1 ответ
Создайте преобразователь тела ответа, который принимает источник тела ответа, пропускает начальные байты и делегирует. Вот пример с добавленной аннотацией для пометки методов обслуживания, которые имеют этот префикс в своих телах ответов.
final class Foo {
long timestamp;
int error;
}
interface FooService {
@EqualsJson @GET("/") Call<Foo> foo();
}
@Test public void foo() throws IOException {
MockWebServer server = new MockWebServer();
server.enqueue(new MockResponse().setBody("info={'timestamp':1292608331,'error':0}"));
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(server.url("/"))
.addConverterFactory(new EqualsJson.ResponseBodyConverterFactory())
.addConverterFactory(MoshiConverterFactory.create().asLenient())
.build();
FooService fooService = retrofit.create(FooService.class);
Call<Foo> call = fooService.foo();
Response<Foo> response = call.execute();
Foo body = response.body();
assertThat(body.timestamp).isEqualTo(1292608331);
assertThat(body.error).isEqualTo(0);
}
@Retention(RUNTIME)
public @interface EqualsJson {
final class ResponseBodyConverterFactory extends Converter.Factory {
@Nullable
@Override
public Converter<ResponseBody, ?> responseBodyConverter(
Type type, Annotation[] annotations, Retrofit retrofit) {
for (int i = 0; i < annotations.length; i++) {
Annotation annotation = annotations[i];
if (annotation instanceof EqualsJson) {
Annotation[] nextAnnotations = new Annotation[annotations.length - 1];
System.arraycopy(
annotations, 0, nextAnnotations, 0, i);
System.arraycopy(
annotations, i + 1, nextAnnotations, i, annotations.length - i - 1);
return new ResponseBodyConverter(
retrofit.nextResponseBodyConverter(this, type, nextAnnotations));
}
}
return null;
}
static final class ResponseBodyConverter implements Converter<ResponseBody, Object> {
static final ByteString JSON_PREFIX = ByteString.encodeUtf8("=");
final Converter<ResponseBody, ?> delegate;
ResponseBodyConverter(Converter<ResponseBody, Object> delegate) {
this.delegate = delegate;
}
@Override
public Object convert(ResponseBody value) throws IOException {
BufferedSource source = value.source();
source.skip(source.indexOf(JSON_PREFIX) + 1);
return delegate.convert(
ResponseBody.create(value.contentType(), value.contentLength(), source));
}
}
}
}