【问题标题】:Moshi Expected BEGIN_OBJECT but was BEGIN_ARRAY - custom converter ignoredMoshi 预期 BEGIN_OBJECT 但为 BEGIN_ARRAY - 自定义转换器被忽略
【发布时间】:2018-08-19 02:54:15
【问题描述】:

我使用 Moshi 作为 Retrofit 的转换器,但是对于一个特定的请求,它不起作用并且抛出异常: com.squareup.moshi.JsonDataException: Expected BEGIN_OBJECT but was BEGIN_ARRAY at path $.results

我要解析的 JSON:

{
  "id": 423,
  "results": [
    {
      "id": "53484dfec3a3684b930000bd",
      "iso_639_1": "en",
      "iso_3166_1": "US",
      "key": "u_jE7-6Uv7E",
      "name": "Trailer",
      "site": "YouTube",
      "size": 360,
      "type": "Trailer"
    },
    {
      "id": "57e16bb0c3a36808bc000641",
      "iso_639_1": "en",
      "iso_3166_1": "US",
      "key": "BFwGqLa_oAo",
      "name": "Trailer",
      "site": "YouTube",
      "size": 1080,
      "type": "Trailer"
    }
  ]
}

模型类:

public class VideosResponse {
    private int id;
    private List<Video> results;
    //+ getters & setters
}
public class Video {
    private String id;
    @Json(name = "iso_639_1")
    private String iso6391;
    @Json(name = "iso_3166_1")
    private String iso31661;
    private String key;
    private String name;
    private String site;
    private Integer size;
    private String type;
    //+getters & setters
}

这是改造电话:

@GET("3/movie/{id}/videos")
Call<List<Video>> movieVideos(
      @Path("id") int id,
      @Query("api_key") String apiKey);

如您所见,我期待对象列表,但 JSON 实际上本身就是一个对象,因此我准备了我的自定义转换器:

public class VideosJsonConverter {
    @FromJson
    public List<Video> fromJson(VideosResponse json) {
        return json.getResults();
    }
}

...我将它添加到我的改造中:

public Retrofit provideRetrofit(@Named("baseUrl") String basUrl) {
        Moshi moshi = new Moshi.Builder().add(new VideosJsonConverter()).build();
        return new Retrofit.Builder()
                .baseUrl(basUrl)
                .addConverterFactory(MoshiConverterFactory.create(moshi))
                .build();
    }

我的自定义转换器实际上并没有被调用,所以看起来 Moshi 无法将 JSON 转换为我的 VideosResponse 包装类。如果我将我的转换器更改为接受Map&lt;String, Object&gt;,它会去那里,但不适用于VideosResponse。当我将改造点更改为直接返回 VideosResponse 时,它也可以工作。是否可能与其他 POJO 类发生冲突(我有类似的类但有不同对象的列表)?

【问题讨论】:

    标签: java json retrofit2 moshi


    【解决方案1】:

    问题是适配器将被您想要的结果和 VideosResponse 中的内部列表使用。因此,适配器在 VideoResponse 中期待一个 VideoResponse 格式的 JSON blob,并在重新进入时找到真正的数组时失败。

    您可以限定其中一个列表以区分它们。 这是限定结果列表的示例。

    @Retention(RUNTIME)
    @JsonQualifier
    public @interface Wrapped {
    }
    
    public class VideosJsonConverter {
      @Wrapped @FromJson
      public List<Video> fromJson(VideosResponse json) {
        return json.results;
      }
    
      @ToJson
      public VideosResponse toJson(@Wrapped List<Video> value) {
        throw new UnsupportedOperationException();
      }
    }
    
    @GET("3/movie/{id}/videos")
    @Wrapped
    Call<List<Video>> movieVideos(
      @Path("id") int id,
      @Query("api_key") String apiKey);
    

    【讨论】:

    • 感谢您的解释。我没有意识到这一点,因为我实际上不知道它是如何工作的。
    猜你喜欢
    • 2020-03-06
    • 2019-05-10
    • 1970-01-01
    • 2015-07-24
    • 2014-08-01
    • 2015-11-26
    • 2018-03-27
    • 2016-08-20
    • 2019-06-14
    相关资源
    最近更新 更多