使用Halarious和Teleport.org进行改造

时间:2016-04-04 10:25:39

标签: java android json api

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

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/

我已经这样设置了。

MainActivity:

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课程。

CityData:

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给我带来了问题。这是为什么?

亲切的问候,

的Wouter

2 个答案:

答案 0 :(得分:1)

我认为这是因为原始响应变量名称为ua:Item,而不是uaItem。可能自动映射在这里不起作用。您可以通过显式写出变量名来修复它:

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

答案 1 :(得分:0)

您需要在每个链接上添加@HalLink。您忘了在CityData.self

上添加它

如果您必须指定其他名称,请使用name属性。

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