Android 如何在改装2中使用gson类型适配器?

Android 如何在改装2中使用gson类型适配器?,android,gson,retrofit2,Android,Gson,Retrofit2,我有一个工作代码,我的改造客户端可以从api中检索对象列表(国家)。问题是,api使用的参数返回一个数组,如果我用来检索所有国家,那么当我要查询单个国家时,它将返回单个对象。因此,将显示以下异常 java.lang.IllegalStateException: Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 4 column 17 path $.RestResponse.result 顺便说一下,我用的是改装2 我试着用这条线索来回答这个问题

我有一个工作代码,我的改造客户端可以从api中检索对象列表(国家)。问题是,api使用的参数返回一个数组,如果我用来检索所有国家,那么当我要查询单个国家时,它将返回单个对象。因此,将显示以下异常

java.lang.IllegalStateException: Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 4 column 17 path $.RestResponse.result
顺便说一下,我用的是改装2

我试着用这条线索来回答这个问题

但还是不行。这是我的实现

原料药

ApiInterface

public interface ApiInterface {

    @GET("country/get/all")
    Call<Example> getCountry();

    @GET("country/get/iso2code/{alpha2_code}")
    Call<Example> searchCountryByIso2Code(@Path("alpha2_code") String alpha2Code);

    @GET("country/get/iso3code/{alpha3_code}")
    Call<Example> searchCountryByIso3Code(@Path("alpha3_code") String alpha3Code);

    @GET("country/search?text={text to search}")
    Call<Example> searchCountry(@Path("text to search") String searchText);
}
编辑: 重新响应

public class RestResponse {

    @SerializedName("messages")
    @Expose
    private List<String> messages = null;
    @SerializedName("result")
    @Expose
    private List<Result> result = null;

    public RestResponse() {
    }

    public RestResponse(List<String> messages, List<Result> result) {
        this.messages = messages;
        this.result = result;
    }

    public RestResponse(Result... result) {
        this.result = Arrays.asList(result);
    }

    public List<String> getMessages() {
        return messages;
    }

    public void setMessages(List<String> messages) {
        this.messages = messages;
    }

    public List<Result> getResult() {
        return result;
    }

    public void setResult(List<Result> result) {
        this.result = result;
    }


}
公共类重新响应{
@SerializedName(“消息”)
@暴露
私有列表消息=null;
@SerializedName(“结果”)
@暴露
私有列表结果=null;
公共厕所(){
}
公共重新响应(列出消息、列出结果){
this.messages=消息;
this.result=结果;
}
公共重新响应(结果…结果){
this.result=Arrays.asList(result);
}
公共列表getMessages(){
返回消息;
}
公共消息(列出消息){
this.messages=消息;
}
公共列表getResult(){
返回结果;
}
公共void setResult(列表结果){
this.result=结果;
}
}

您的代码中存在一些问题,其中一些问题可以修复或重新设计,以简化很多事情。首先,让我们看看服务(名字不同)。对于带有查询参数的请求,改装接口必须使用
@Query
,而不是
@Path
。此外,您的服务方法必须返回一个
调用
,其中它的
T
声明实际的结果类型,提供有关该方法返回的内容的一些信息。您提到的服务可以返回单个元素,也可以不返回任何元素(但由于某些原因永远不会返回HTTP 404),或者根据端点URL返回列表。让我们假设,单值和无值并不意味着是1或0大小的列表:

接口设备{
@获取(“国家/获取/全部”)
调用getCountries();
@GET(“国家/地区/GET/iso2code/{code}”)
调用getCountryByIso2Code(
@路径(“代码”)字符串代码
);
@GET(“国家/地区/GET/iso3code/{code}”)
调用getCountryByIso3Code(
@路径(“代码”)字符串代码
);
@获取(“国家/地区/搜索”)
呼叫搜索国家/地区(
@查询(“文本”)字符串查询
);
}
接下来,
Country
类可能如下所示:

final class国家/地区{
@序列化名称(“名称”)
最终字符串名称=null;
@序列化名称(“字母2_代码”)
最终字符串code2=null;
@序列化名称(“字母3_代码”)
最终字符串code3=null;
@凌驾
公共字符串toString(){
返回name+'('+code2+'、'+code3+');
}
}
请注意,
@SerializedName
可以将外部名称映射到本地字段名,字段是
final
null
ified-Gson可以自己处理它们。接下来,我假设您并不真正关心响应结构,只需要分别调整的
$.response.result
TypeAdapterFactory
是您所需要的,可以处理任何响应,不一定适用于以下国家:

最终类响应ExtractorTypeAdapterFactory
实现TypeAdapterFactory{
私人最终Gson Gson;
私人响应ExtractortTypeAdapterFactory(最终Gson Gson){
this.gson=gson;
}
静态类型适配器工厂getResponseExtractorTypeAdapterFactory(最终Gson Gson){
返回新的响应ExtractortTypeAdapterFactory(gson);
}
@凌驾
公共类型适配器创建(最终Gson响应,最终TypeToken TypeToken){
//使用responseGson将导致无限递归,因为此类型适配器工厂将覆盖任何类型
返回新的responseExtractortTypeAdapter(gson,typeToken.getType());
}
私有静态最终类响应ExtractortTypeAdapter
扩展类型适配器{
私人最终Gson Gson;
私有最终类型;
专用响应ExtractortTypeAdapter(最终Gson Gson,最终类型){
this.gson=gson;
this.type=type;
}
@凌驾
公共无效写入(最终JsonWriter out,最终T值){
抛出新的UnsupportedOperationException();
}
@凌驾
公共T读(最终JsonReader in)
抛出IOException{
T结果=null;
//剥去最上面的{$
in.beginObject();
最终字符串名称1=in.nextName();
开关(名称1){
案例“重新响应”:
//Response{for$.Response
in.beginObject();
while(在.hasNext()中){
最终字符串名称2=in.nextName();
开关(名称2){
案例“信息”:
//如果只是$.Response.message,则跳过它
in.skipValue();
打破
案例“结果”:
//如果是$.Response.result,则将其委托给“real”Gson
result=gson.fromJson(in,type);
打破
违约:
抛出新的MalformedJsonException(“在$.RestResponse处意外:“+name2”);
}
}
//$.Response的Response}
in.endObject();
打破
违约:
抛出新的MalformedJsonException(“在$:“+name1处意外”);
}
//剥去最上面的封闭区域}$
in.endObject();
返回结果;
}
}
}
总而言之:

publicstaticvoidmain(最终字符串…args){
最终Gson Gson=新的GsonBuilder(
public class CountryTypeAdapter extends TypeAdapter<RestResponse> {

    private Gson mGson = new Gson();

    @Override
    public void write(JsonWriter jsonWriter, RestResponse restResponse) throws IOException {
        mGson.toJson(restResponse, RestResponse.class, jsonWriter);
    }

    @Override
    public RestResponse read(JsonReader jsonReader) throws IOException {
        RestResponse result;

        jsonReader.beginObject();
        jsonReader.nextName();

        if (jsonReader.peek() == JsonToken.BEGIN_ARRAY) {
            result = new RestResponse((Result[]) mGson.fromJson(jsonReader, Result.class));
        } else if (jsonReader.peek() == JsonToken.BEGIN_OBJECT) {
            result = new RestResponse((Result) mGson.fromJson(jsonReader, Result.class));
        } else {
            throw new JsonParseException("Unexpected token " + jsonReader.peek());
        }

        jsonReader.endObject();
        return result;
    }
}
public class ApiClient {

    public static final String BASE_URL = "http://services.groupkt.com/";
    private static Retrofit mRetrofit;

    public static Retrofit getmRetrofitClient(){

        if (mRetrofit == null) {
            mRetrofit = new Retrofit.Builder()
                    .baseUrl(BASE_URL)
                    .addConverterFactory(GsonConverterFactory.create(new GsonBuilder().registerTypeAdapter(CountryTypeAdapter.class, new CountryTypeAdapter()).create()))
                    .build();
        }
        return mRetrofit;
    }

}
public class RestResponse {

    @SerializedName("messages")
    @Expose
    private List<String> messages = null;
    @SerializedName("result")
    @Expose
    private List<Result> result = null;

    public RestResponse() {
    }

    public RestResponse(List<String> messages, List<Result> result) {
        this.messages = messages;
        this.result = result;
    }

    public RestResponse(Result... result) {
        this.result = Arrays.asList(result);
    }

    public List<String> getMessages() {
        return messages;
    }

    public void setMessages(List<String> messages) {
        this.messages = messages;
    }

    public List<Result> getResult() {
        return result;
    }

    public void setResult(List<Result> result) {
        this.result = result;
    }


}