我正在开发一个小型的Android应用程序,该应用程序使用teleport.org API列出了市区。为此,我使用以下响应URL:

https://api.teleport.org/api/urban_areas/

响应如下所示:

{
  "_links": {
    "curies": [
      {
        "href": "https://developers.teleport.org/api/resources/Location/#!/relations/{rel}/",
        "name": "location",
        "templated": true
      }
    ],
    "self": {
      "href": "https://api.teleport.org/api/urban_areas/"
    },
    "ua:item": [
      {
        "href": "https://api.teleport.org/api/urban_areas/teleport:u173z/",
        "name": "Amsterdam"
      }
    ]
  },
  "count": 153
}


这给了我一个HAL格式的json文件。由于我正在使用改造来加载我的API,因此我需要一个自定义转换器,以将该信息存储在POJO类中。我为此选择了Halarious。 http://halarious.ch/

我已经这样设置了。

主要活动:

String url = "https://api.teleport.org/api/";
TextView txt_city;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
    txt_city = (TextView) findViewById(R.id.txt_city);

    setSupportActionBar(toolbar);

    FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
    fab.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
                    .setAction("Action", null).show();
        }
    });

    getCities();

}

void getCities() {
    //Creating Rest Services
    Retrofit retrofit = new Retrofit.Builder()
            .baseUrl(url)
            .addConverterFactory(HALConverterFactory.create(CityData.class))
            .build();

    RestInterface service = retrofit.create(RestInterface.class);

    Call<CityData> call = service.getCityList();


    call.enqueue(new Callback<CityData>() {
        @Override
        public void onResponse(Call<CityData> call, Response<CityData> response) {
            try {
                String city = response.body().getUaItem().get(0).getName();
                //Log.e("stad", city);

                txt_city.setText("city 12  :  " + city);

            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onFailure(Call<CityData> call, Throwable t) {
            // Log error here since request failed
        }
    });
}


HALConverterFactory.class:

public final class HALConverterFactory extends Converter.Factory {
    private final Gson gson;

    public static HALConverterFactory create(Class<?> type) {
        return new HALConverterFactory(type);
    }

    private HALConverterFactory(Class<?> type) {
        if (!HalResource.class.isAssignableFrom(type))
            throw new NullPointerException("Type should be a subclass of HalResource");
        GsonBuilder builder = new GsonBuilder();
        builder.registerTypeAdapter(HalResource.class, new HalSerializer());
        builder.registerTypeAdapter(HalResource.class, new HalDeserializer(type));
        builder.setExclusionStrategies(new HalExclusionStrategy());
        this.gson = builder.create();
    }

    @Override
    public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, Retrofit retrofit) {
        return new HALResponseBodyConverter<>(gson);
    }

    @Override
    public Converter<?, RequestBody> requestBodyConverter(Type type, Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) {
        return super.requestBodyConverter(type, parameterAnnotations, methodAnnotations, retrofit);
    }
}


HALResponseBodyConverter.class:

final class HALResponseBodyConverter<T extends HalResource> implements Converter<ResponseBody, T>{

    private final Gson gson;

    HALResponseBodyConverter(Gson gson) {
        this.gson = gson;
    }

    @Override public T convert(ResponseBody value) throws IOException {
        BufferedSource source = value.source();
        try {
            String s = source.readString(Charset.forName("UTF-8"));
            return (T) gson.fromJson(s, HalResource.class);
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            closeQuietly(source);
        }
    }

    private static void closeQuietly(Closeable closeable) {
        if (closeable == null) return;
        try {
            closeable.close();
        } catch (IOException ignored) {
        }
    }
}


我有以下POJO类。

城市数据:

public class CityData implements HalResource {

    @HalLink
    private List<Cury> curies = new ArrayList<Cury>();
    private Self self;
    private List<UaItem> uaItem = new ArrayList<UaItem>();
    private Map<String, Object> additionalProperties = new HashMap<String, Object>();

    private Integer count;

    //getters and setters
}


UaItem:

public class UaItem implements HalResource {
    @HalLink
    private String href;
    private String name;
    private Map<String, Object> additionalProperties = new HashMap<String, Object>();
    //getters and setters
}


我现在想做的是检索以下内容:

String city = response.body().getUaItem().get(0).getName();


但是问题是我的getUaItem完全为空。它只返回[]。由于数组为空,因此get(0)是无用的。我可以得到这个数字,因为那是最高级别,但是UaItem导致了我的麻烦。为什么是这样?

亲切的问候,

伍特

最佳答案

我认为这是由于原始响应变量名称是ua:Item而不是uaItem造成的。自动映射可能在这里不起作用。您可以通过显式写出变量名来解决它:

@serializedName("ua:item") private List<UaItem> uaItem = new ArrayList<UaItem>();

07-24 09:21