使用Gson反序列化JSON数组?

5
我的json如下:

以下是代码:

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

以下是我的类别模型:

public class Category {

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

我的gson自定义反序列化器如下所示:
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);
    }
}

我正在使用Retrofit库,它使用gson来序列化/反序列化JSON对象。我将此自定义gson反序列化器传递给retrofit,但它会给我返回一个错误。您能告诉我在反序列化时哪里出错了吗?

错误:

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

预期结果:
我想从json中获取类别的Arraylist。

你应该说出你得到的确切错误。此外,你的JSON无效:所有成员名称都应该用引号括起来("status",“catId”等)。 - Tommi
@Tommi 我编辑了问题,请检查! - Ram Patra
创建一个带有 public int statuspublic ArrayList<Category> data 的超类不是更容易吗?请查看此问题的被接受答案中的示例。 - Tommi
我可以接受这个,但我正在寻找更好的解决方案,仅为了Gson序列化/反序列化而创建包装对象并不是正确的方法。 - Ram Patra
1
很遗憾,我现在无法设置环境来运行测试项目,所以我只能猜测一些东西。你重写的反序列化方法返回Category实例(而不是类别数组或ArrayList)。然而,当你获取json.get("data") JSON字符串时,它包含一个数组(根据你的示例数据),而你的TypeToken是通用类别集合。因此,看起来你试图返回类别列表,而期望的是一个类别实例。这就是为什么你会得到类型转换错误的原因。顺便说一句:我相信创建包装对象是你正在寻找的更好的解决方案。 - Tommi
我找到了错误,将 deserialize 的返回类型从Category 改为 ArrayList<Category> 就可以解决问题。感谢您指出这一点。这意味着我们可以采用这种方法,而不必创建包装对象。 - Ram Patra
2个回答

3
deserialize()的返回类型从Category更改为ArrayList<Category>解决了问题。其余代码正确。

2

看起来你只是想从JSON中提取一个ListCategory对象。你需要让你的反序列化程序来完成这个任务,并使用TypeToken来注册你的反序列化程序。

这里有一个完整的工作示例。显然,你可以根据需要更改类的范围;我将它们更改为单个文件示例。

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;
    }

}

输出:

分类编号:638.0


非常感谢您的回答,实际上我的代码是正确的,只是deserialize的返回类型不对。我将其改为 ArrayList<Category>,现在它可以正常工作了。无论如何,非常感谢您的帮助。 - Ram Patra

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接