5

I have my json as:

{
   "status": 200,
   "data": [
       {
            "catId": 638,
            "catName": "Helena Bonham Carter",
            "catUniqueName": "helena-bonham-carter",
            "catSlug": ""
       },
       {
        ...
       }
   ]
}

My Category model as:

public class Category {

    private double catId;
    private String catName;
    private String catUniqueName;
    private String catSlug;
}

And my gson custom deserializer is as follows:

Type listType = new TypeToken<ArrayList<Category>>(){}.getType();

Gson gson = new GsonBuilder()
            .registerTypeAdapter(listType, new CategoryDeserializer())
            .create();

private class CategoryDeserializer implements JsonDeserializer {
    @Override
    public Category deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
            throws JsonParseException {
        Gson gson = new Gson();
        return gson.fromJson(((JsonObject) json).get("data"), typeOfT);
    }
}

I am using Retrofit library which uses gson to serialize/deserialize json objects. I pass this custom gson deserializer to retrofit but it gives me an error. Can you tell me where I am going wrong while desrializing?

Error:

java.util.ArrayList cannot be cast to com.compzets.app.models.Category

Expected Result:

I want ArrayList of Category from json.

6
  • You should say what exact error you get. Also your JSON is invalid: all member names should be in quotes ("status", "catId" etc.) Commented Dec 27, 2014 at 11:10
  • @Tommi I edited the question, please check! Commented Dec 27, 2014 at 11:16
  • Wouldn't it be easier to create super-class with public int status and public ArrayList<Category> data? Check sample in accepted answer for this question Commented Dec 27, 2014 at 11:30
  • I can go with that but i was looking for a better solution, creating wrapper objects just for gson serialization/deserialization isn't the way to go. Commented Dec 27, 2014 at 12:15
  • 1
    Unfortunately, I cannot setup environment to run test project right now, so I can only make some guesses. Your deserializer method you're overriding returns Category instance (not array or arraylist of categories). However, when you get json.get("data") JSON string contains array (according to your sample data), and your TypeToken is generic collection of categories. So it looks like you're trying to return list of Categories, when one Category instance is expected. That's why you get cast error. Side note: I belive that create wrapper object IS better solution you're looking for. Commented Dec 27, 2014 at 12:47

2 Answers 2

3

Changing the return type of deserialize() from Category to ArrayList<Category> solved the issue. Rest of the code is correct.

Sign up to request clarification or add additional context in comments.

Comments

2

It would appear you're just trying to only extract a List of your Category objects from the JSON. You need your deserializer to do that, and use TypeToken accordingly to register your deserializer.

Here's a complete working example. Obviously you can change the class scoping as needed; I changed them to make it a single file example.

public class App 
{
    public static void main( String[] args )
    {
        String json = "{\n" +
            "   \"status\": 200,\n" +
            "   \"data\": [\n" +
            "       {\n" +
            "            \"catId\": 638,\n" +
            "            \"catName\": \"Helena Bonham Carter\",\n" +
            "            \"catUniqueName\": \"helena-bonham-carter\",\n" +
            "            \"catSlug\": \"\"\n" +
            "       }\n" +
            "   ]\n" +
            "}";

        Type listType = new TypeToken<List<Category>>(){}.getType();
        Gson gson = new GsonBuilder().registerTypeAdapter(listType, new CategoryDeserializer()).create();

        List<Category> list = gson.fromJson(json, listType);

        for (Category c : list)
        {
            System.out.println("CatId: " + c.catId);
        }


    }

    public static class CategoryDeserializer implements JsonDeserializer<List<Category>>
    {

        public List<Category> deserialize(JsonElement je, Type type, JsonDeserializationContext jdc) throws JsonParseException
        {
            JsonArray data = je.getAsJsonObject().getAsJsonArray("data");
            ArrayList<Category> myList = new ArrayList<Category>();

            for (JsonElement e : data)
            {
                myList.add((Category)jdc.deserialize(e, Category.class));
            }

            return myList;

        }

    }

    public static class Category
    {
        public double catId;
        public String catName;
        public String catUniqueName;
        public String catSlug;
    }

}

Output:

CatId: 638.0

1 Comment

Thank you very much for the answer, actually my code was correct except for the return type of deserialize. I changed it to ArrayList<Category> and is now working fine. Anyways thanks a ton for the help.

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.