1

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()".

1
  • Try removing Category2 Copy Constructor. If there is a Copy Constructor available, no default Constructror is called when you make new Category2 Class objects. Try this and tell me if it works Commented Aug 31, 2017 at 13:55

2 Answers 2

5

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());
    }
});
Sign up to request clarification or add additional context in comments.

11 Comments

Thanks for the reply! I try to do the changes that you suggested but I am still getting: attempt to invoke virtual method 'int java.util.ArrayList.size()' on a null object reference. And I know that the result should not come back as null given the token and projectID that I am passing.
could it be because of the retrofit service? You should use the @Path("projectId") annotation instead of @Query("projectId") when you want to add the parameter to the call path.
I changed for "@Path" but I'm getting the same error. I am testing the link using Postman and it's working fine, retrieving the results that it's supposed to. But in Postman when I add the header I add the Key which is "Authorization" and the value, which is the token. In the app I am not adding the key. Do you think it's because of that?
Yes I think that should be the cause! By the way what is the http code returned by the current call?
Can you please tell me how do I get the http response code?
|
0

Add the new fields to the class Category2 with the indication they are transient, i.e, 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());

1 Comment

Thanks for the reply! I did what you suggested but I am getting: Attempt to invoke virtual method 'java.util.List com.construct.v2.models.category.CategoryResponse.getResults()' on a null object reference But I know that for the token and ProjectID I am passing I should not get a null response.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.