【问题标题】:parse api response not completly "json" with retofit and Moshi使用改造和 Moshi 解析 api 响应不完全是“json”
【发布时间】:2019-05-05 03:03:07
【问题描述】:

我找到了我想尝试的 api,但响应不是 "full 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}

有什么办法解析吗?

【问题讨论】:

  • MoshiConverterFactory.create().asLenient() 会像 {search={'error':1}} 那样工作。如果它根本不像 JSON,您可能需要先阅读部分响应正文,然后再委托。
  • 谢谢@EricCochran。我会看看。今天下午告诉你一些事情。
  • @EricCochran 没有工作,实际上不是 json。如何解析正文?
  • 我会有一个 Retrofit 响应正文转换器,它获取正文的源,找到第一个等号的索引,跳过该索引,然后委托给一个宽松的 JSON 响应正文转换器。

标签: android json api retrofit2 moshi


【解决方案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));
      }
    }
  }
}

【讨论】:

    猜你喜欢
    • 2020-09-26
    • 1970-01-01
    • 2021-06-27
    • 1970-01-01
    • 1970-01-01
    • 2020-03-19
    • 2015-08-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多