用动态键改造gson [英] Retrofit gson with dynamic keys

查看:59
本文介绍了用动态键改造gson的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我设法在没有动态键的情况下使其正常工作.通过遵循

这是响应格式:

  {"dynamic1":{"cityID":"id1","priceRange":15},"dynamic2":{"cityID":"id2","priceRange":15}} 

在APIUtils.java

 公共静态CityService getCitiesService(){返回RetrofitClient.getClient(BASE_URL).create(CityService.class);} 

在CityService.java

 公共接口CityService {@GET("/SAGetStrollAwayCity")呼叫< CityResponse>getCities();@GET("/SAGetStrollAwayCity")呼叫< CityResponse>getCities(@Query("tagged")String标签);} 

在CityResponse.java中:

 公共类CityResponse {/* @ SerializedName("results")@ Expose *///这是正确的方法吗?私人地图< String,CityDetails>city = new HashMap<>();公共地图< String,CityDetails>getCity(){返回城市;}public void setCity(Map< String,CityDetails> elemDetails){this.city = elemDetails;}} 

在CityDetails.java中

 公共类CityDetails {@SerializedName("cityID")@暴露私有String cityID;@SerializedName("priceRange")@暴露私有Integer priceRange;公共字符串getCityID(){返回cityID;}公共无效setCityID(String cityID){this.cityID = cityID;}public Integer getPriceRange(){返回priceRange;}public void setPriceRange(Integer priceRange){this.priceRange = priceRange;}} 

在HomeFragment.java中

  public View onCreateView(@NonNull LayoutInflater充气机,@ Nullable ViewGroup容器,@ Nullable Bundle saveInstanceState){查看rootView = inflater.inflate(R.layout.fragment_home,null);//第二次api调用mServiceCity = ApiUtils.getCitiesService();loadCities();返回rootView;}公共无效loadCities(){mServiceCity.getCities().enqueue(new Callback< CityResponse>(){@Overridepublic void onResponse(Call< CityResponse>呼叫,Response< CityResponse>响应){//!!!为什么响应身体为空???if(response.isSuccessful()){//adapter.updateCities(response.body().getCity());Log.d("MainActivity",从API加载的帖子" + response.body().getCity());}别的 {int statusCode = response.code();//根据状态码处理请求错误}}@Override公共无效onFailure(Call< CityResponse>呼叫,Throwable t){//showErrorMessage();Log.d("MainActivity",从API加载错误");}});} 

解决方案

我个人将删除 CityResponse 模型,并仅使用 Map< String,CityDetails> .

改装界面可以是:

 公共接口CityService {@GET("/SAGetStrollAwayCity")呼叫< Map< String,CityDetails>>getCities();@GET("/SAGetStrollAwayCity")呼叫< Map< String,CityDetails>>getCities(@Query("tagged")String标签);} 

在您的方案中,响应正文为空,因为 CityResponse 将映射到以下json:

  {城市": {"dynamic1":{"cityID":"id1","priceRange":15},"dynamic2":{"cityID":"id2","priceRange":15}}} 

但是,您没有名为 city 的根元素.json本身已经可以映射到java Map .

希望这会有所帮助.

I've managed to get it to work without a dynamic key. By following this tutorial with this json:

Currently, I'm using Retrofit and trying to get a response with dynamic keys. However, the response body is always null:

This is the response format:

{
    "dynamic1": {
        "cityID": "id1",
        "priceRange": 15
    },
    "dynamic2": {
        "cityID": "id2",
        "priceRange": 15
    }
}

In APIUtils.java

    public static CityService getCitiesService() {
        return RetrofitClient.getClient(BASE_URL).create(CityService.class);
    }

In CityService.java

public interface CityService {

    @GET("/SAGetStrollAwayCity")
    Call<CityResponse> getCities();

    @GET("/SAGetStrollAwayCity")
    Call<CityResponse> getCities(@Query("tagged") String tags);
}

In CityResponse.java:

public class CityResponse {
    /*@SerializedName("results")
    @Expose*/ // is this the correct way?
    private Map<String, CityDetails> city = new HashMap<>();

    public Map<String, CityDetails> getCity() {
        return city;
    }

    public void setCity(Map<String, CityDetails> elemDetails) {
        this.city = elemDetails;
    }

}

In CityDetails.java

public class CityDetails {

    @SerializedName("cityID")
    @Expose
    private String cityID;
    @SerializedName("priceRange")
    @Expose
    private Integer priceRange;

    public String getCityID() {
        return cityID;
    }

    public void setCityID(String cityID) {
        this.cityID = cityID;
    }

    public Integer getPriceRange() {
        return priceRange;
    }

    public void setPriceRange(Integer priceRange) {
        this.priceRange = priceRange;
    }

}

In HomeFragment.java

public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.fragment_home, null);
        // 2nd api call
        mServiceCity = ApiUtils.getCitiesService();
        loadCities();

        return rootView;
}

public void loadCities() {
    mServiceCity.getCities().enqueue(new Callback<CityResponse>() {
        @Override
        public void onResponse(Call<CityResponse> call, Response<CityResponse> response) {
         // !!! WHY IS THE RESPONSE BODY EMPTY???
            if(response.isSuccessful()) {

//                    adapter.updateCities(response.body().getCity());

                Log.d("MainActivity", "posts loaded from API"+ response.body().getCity());
            }else {
                int statusCode  = response.code();
                // handle request errors depending on status code
            }
        }

        @Override
        public void onFailure(Call<CityResponse> call, Throwable t) {
            //showErrorMessage();
            Log.d("MainActivity", "error loading from API");

        }
    });
}

解决方案

Personally I'd drop the CityResponse model and just work with Map<String, CityDetails>.

The retrofit interface can then be:

public interface CityService {

  @GET("/SAGetStrollAwayCity")
  Call<Map<String, CityDetails>> getCities();

  @GET("/SAGetStrollAwayCity")
  Call<Map<String, CityDetails>> getCities(@Query("tagged") String tags);
}

In your scenario, the response body is empty because CityResponse would map to a json like:

{
  "city": {
    "dynamic1": {
      "cityID": "id1",
      "priceRange": 15
    },
    "dynamic2": {
      "cityID": "id2",
      "priceRange": 15
    }
  }
}

However, you don't have a root element called city. The json itself can already be mapped to a java Map.

Hope this helps.

这篇关于用动态键改造gson的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆