简体   繁体   中英

Android - JSON parsing without the array title using Retrofit

I am facing some difficulties when getting a JSON String and using it in my Android app. So, I have this class Category2, where I have defined all the fields a category must have:

public class Category2 {

    @SerializedName("_id")
    private String _id;
    @SerializedName("name")
    private String name;
    @SerializedName("tasks")
    private int tasks;

    public Category2(String _id, String name, int tasks) {

        this._id = _id;
        this.name = name;
        this.tasks = tasks;
    }


    public String get_id(){
        return _id;
    }
    public void set_id(String _id){
        this._id = _id;
    }
    public String getName(){
        return name;
    }
    public void setName(String name){
        this.name = name;
    }
    public int getTasks() {
        return tasks;
    }
    public void setTasks(int tasks){
        this.tasks = tasks;
    }
}

And I have a class called CategoryResponse that is basically a list of category2 that I get from the retrofit request:

public class CategoryResponse {

    private List<Category2> results;

    public List<Category2> getResults() {
        return results;
    }

    public void setResults(List<Category2> results) {
        this.results = results;
    }
}

Generally I deal with JSON strings that have a name for the results even when it's a list of items like:

{"genres":[{"id":28,"name":"Action"},{"id":12,"name":"Adventure"}]}

When the JSON string is like the above I just add a Serialized for the list results above the declaration of the List:

@SerializedName("genres")

And it works just fine when I declare my GET method:

@GET("/v3/projects/{projectId}/categories/")
    Call<CategoryResponse> getProjectCategories(@Query("projectId") String projectId, @Header("Token") String token);

And I call it in my Activity:

categoryService =
        CategoryClient.getClient().create(CategoryService.class);

Call<CategoryResponse> call = categoryService.getProjectCategories(projectId,token);
call.enqueue(new Callback<CategoryResponse>() {
    @Override
    public void onResponse(Call<CategoryResponse> call, Response<CategoryResponse> response) {

        //int statusCode = response.code();
        listCategories = new ArrayList<>();
        listCategories = response.body().getResults();
        System.out.println("Size: " + response.body().getResults().size());
    }

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

But what I have now for the categories is something like this:

[
    {
        "_id": "59a6b18b2ba5c14bb76f28c8",
        "createdAt": "2017-08-30T12:37:31.885Z",
        "updatedAt": "2017-08-30T12:37:31.885Z",
        "projectId": "598cbc74a1d0e57722ca98d1",
        "companyId": "5602eb7ce49c9cd70409f206",
        "name": "Arquitetura",
        "__v": 0,
        "tasks": 0
    },
    {
        "_id": "59a6b1be2ba5c14bb76f28c9",
        "createdAt": "2017-08-30T12:38:22.407Z",
        "updatedAt": "2017-08-30T12:38:22.407Z",
        "projectId": "598cbc74a1d0e57722ca98d1",
        "companyId": "5602eb7ce49c9cd70409f206",
        "name": "Manutenção",
        "__v": 0,
        "tasks": 0
    }
]

So I cannot serialize the name of the list of results and I am getting null when I call "response.body.GetResults()".

On your service code just return a Call<ArrayList<Category2>>

@GET("/v3/projects/{projectId}/categories/")
Call<ArrayList<Category2>> getProjectCategories(@Path("projectId") String projectId, @Header("Token") String token);

The parsing will be made correctly by retrofit this way.

EDIT

How you call this service:

categoryService =
        CategoryClient.getClient().create(CategoryService.class);

Call<ArrayList<Category2>> call = categoryService.getProjectCategories(projectId,token);
call.enqueue(new Callback<ArrayList<Category2>>() {
    @Override
    public void onResponse(Call<ArrayList<Category2>> call, Response<ArrayList<Category2>> response) {
        listCategories = response.body();
        System.out.println("Size: " + listCategories.size().toString());
    }

    @Override
    public void onFailure(Call<ArrayList<Category2>> call, Throwable t) {
        // Log error here since request failed
        Log.e(TAG, t.toString());
    }
});

Add the new fields to the class Category2 with the indication they are transient, ie, they are not to be serialized. Gson: How to exclude specific fields from Serialization without annotations

public class Category2 {

@SerializedName("_id")
private String _id;
@SerializedName("name")
private String name;
@SerializedName("tasks")
private int tasks;

private transient String createdAt, updatedAt, projectId, companyId;
private transient int __v;

public Category2(String _id, String name, int tasks) {

    this._id = _id;
    this.name = name;
    this.tasks = tasks;
}


public String get_id(){
    return _id;
}
public void set_id(String _id){
    this._id = _id;
}
public String getName(){
    return name;
}
public void setName(String name){
    this.name = name;
}
public int getTasks() {
    return tasks;
}
public void setTasks(int tasks){
    this.tasks = tasks;
}
}

EDIT

Change this

 @GET("/v3/projects/{projectId}/categories/")
Call<List<Category2>> getProjectCategories(@Path("projectId") String projectId, @Header("Authorization") String token);

and this

categoryService =
    CategoryClient.getClient().create(CategoryService.class);

Response<CategoryResponse> response = categoryService.getProjectCategories(projectId,token).execute();

//int statusCode = response.code();
listCategories = new ArrayList<>();
listCategories = response.body().getResults();
System.out.println("Size: " + response.body().getResults().size());

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM