Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get array of objects with gson/retrofit?

I have used gson before to automatically convert to pojo's.

but now im trying to use retrofit to convert an api result to objects.

As long as the json has named arrays of objects this is no problem:

e.g.:

{
    items:[
        {"name":"foo"},
        {"name":"bar"}
    ]
}

public class AnItem {
    String name;
}

public class MyItems {
    List<AnItem> items;
}

public interface MyApi {
    @GET("/itemlist")
    Call<MyItems> loadItems();
}

public boolean onOptionsItemSelected(MenuItem item) {
    Retrofit retrofit = new Retrofit.Builder()
            .baseUrl("https://someurl.com/api")
            .addConverterFactory(GsonConverterFactory.create())
            .build();
    MyApi myApi = retrofit.create(MyApi.class);
    Call<MyApi> call = myApi.loadItems();
    call.enqueue(this);
    return true;
}

@Override
public void onResponse(Response<MyItems> response, Retrofit retrofit) {
    ArrayAdapter<AnItem> adapter = (ArrayAdapter<AnItem>) getListAdapter();
    adapter.clear();
    adapter.addAll(response.body().items);
}

this will automatically work.

but how to do this if the json array isn't named?

e.g.:

[
    {"name":"foo"},
    {"name":"bar"}
]

i know how to do it when not using retrofit with parsejson and iterate over array to get my objects but i cant do it like that because that part is automated with retrofit and gson.

ive been really stuck on this problem for some time now and any pointers would be really appreciated..

UPDATE:

below are the parts i have changed MyItems to List<AnItem>:



public class AllTemplatesRetroActivity extends ListActivity implements Callback<List<AnItem>> {

protected void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);
    requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
    requestWindowFeature(Window.FEATURE_PROGRESS);
    ArrayAdapter<AnItem> arrayAdapter =
            new ArrayAdapter<AnItem>(this,
                    android.R.layout.simple_list_item_1,
                    android.R.id.text1,
                    new ArrayList<AnItem>());
    setListAdapter(arrayAdapter);
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    Retrofit retrofit = new Retrofit.Builder()
        .baseUrl("https://someurl.com/api")
        .addConverterFactory(GsonConverterFactory.create())
        .build();

    MyApi myApi = retrofit.create(MyApi.class);

    Call<List<AnItem>> call = myApi.loadItems();
    call.enqueue(this);
    return true;
}

@Override
public void onResponse(Response<List<AnItem>> response, Retrofit retrofit) {
    ArrayAdapter<AnItem> adapter = (ArrayAdapter<AnItem>) getListAdapter();
    adapter.clear();
    Log.i("##MYLOG###", "## response:"+ response.message());
    adapter.addAll(response.body());
}
like image 280
dilux Avatar asked Jan 05 '16 23:01

dilux


1 Answers

To Handle json response like this:

[
    {"name":"foo"},
    {"name":"bar"}
]

Use Call< List < AnItem>>


In Retrofit2, HttpUrl.resolve() is used to resolve baseUrl and annotated path.

Due to how this works,

This works:

.baseUrl("http://someurl.com")

@GET("/api/itemlist")    --> resolved to http://someurl.com/api/itemlist

or this works

.baseUrl("http://someurl.com/api/")

@GET("itemlist")    --->  resolved to http://someurl.com/api/itemlist

However, this would not work

.baseUrl("http://someurl.com/api")

 @GET("/itemlist")   ---> resolved to http://someurl.com/itemlist
like image 79
Emma Avatar answered Nov 07 '22 00:11

Emma