2016-04-04 55 views
2

我正在研究一个使用teleport.org API列出城市地区的小型Android应用程序。要做到这一点,我使用以下响应网址:用Halarious和Teleport.org进行改造

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

亲切的问候,

沃特

回答

1

我觉得这是一个事实,即原始响应变量名ua:Item,不uaItem造成的。可能自动映射在这里不起作用。您可以通过明确写出变量名来修复它:

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

我不再在这个项目了,所以我不能检查这个位置。我们结束了使用不使用HAL表示法的不同API。所以,把这里留给那些遇到和我一样的问题的人来尝试一下。现在会批准它,直到有人声明为止。 – Wouter125

+0

它不起作用。你需要使用'@HalLink(name =“ua:item”)'。看下面。 – Keysersoze

0

您需要在每个链接上添加@HalLink。您忘记将其添加到CityData.self

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

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