使用GSON解析JSON对象和JSON数组的区别

12

我有一个JSON数据,它可能是一个单独的对象或者是相同对象的数组。是否有一种方法可以使用Gson解析这个数据并区分单个对象和数组?

我目前唯一的解决方案是手动解析json,并将其放在try catch中。首先我会尝试将其解析为单个对象,如果失败了,它会抛出异常,然后我会尝试将其解析为数组。

但我不想手动解析...那需要我花费很长时间。以下是正在发生的事情的概述。

public class ObjectA implements Serializable{

    public String variable;
    public ObjectB[] objectb; //or ObjectB objectb;

    public ObjectA (){}
}

这是一个既可以是数组也可以是单个对象的对象。

public class ObjectB implements Serializable{

    public String variable1;
    public String variable2;

    public ObjectB (){}
}

然后当与JSON响应交互时,我正在做这个。

Gson gson = new Gson();
ObjectA[] objectList = gson.fromJson(response, ObjectA[].class);

当 ObjectA 数组被序列化时,json 包含 ObjectB 的数组或单个对象。

[
    {
        "variable": "blah blah",
        "objectb": {
            "variable1": "1",
            "variable2": "2"
        }
    },
    {
        "variable": "blah blah",
        "objectb": {
            "variable1": "1",
            "variable2": "2"
        }
    },
    {
        "variable": "blah blah",
        "objectb": [
            {
                "variable1": "1",
                "variable2": "2"
            },
            {
                "variable1": "1",
                "variable2": "2"
            }
        ]
    }
]

这是正确的方式: https://dev59.com/NHTYa4cB1Zd3GeqPu3a2#17650863 - Mo1989
3个回答

8

我刚刚将 ObjectB[] 改成了 List<ObjectB>,并应用到 ObjectA 声明中。

ArrayList<ObjectA> la = new ArrayList<ObjectA>();
List<ObjectA> list = new Gson().fromJson(json, la.getClass());

for (Object a : list)
{
   System.out.println(a);
}

这是我的结果:

{variable=blah blah, objectb={variable1=1, variable2=2}}
{variable=blah blah, objectb={variable1=1, variable2=2}}
{variable=blah blah, objectb=[{variable1=1, variable2=2}, {variable1=1, variable2=2}]}

我认为在完整的泛型时代,如果您没有特殊需求,可以从数组转换为列表,这样可以获得许多优势,同时Gson也可以利用这些优势来进行灵活的解析。


这是答案,但现在我遇到了IndexOutOfBoundsException异常,因为有时它尝试解析空值。我会进一步调查的。但还是谢谢! - abounket
1
请随意在SO上添加另一个带有完整堆栈跟踪和代码的问题。我一定会查看它。 - giampaolo
如果“variable1”、“variable2”字段是动态的,你会如何处理?也就是说,你的ObjectB类可能有n个字段。就像这个JSON结构:http://pastebin.com/uUDCKbLV - Ellipsis
抱歉发布了冗余的帖子。我已经弄清楚了如何处理动态变量数量(针对我的问题 ^^)。我没有使用ObjectB类,而是在ObjectA类内部使用Map列表。就像这样:public List<LinkedHashMap<String, String>> objectb = new ArrayList<LinkedHashMap<String, String>>();ObjectA x = new Gson().fromJson(jsonString, ObjectA.class); 感谢您的建议。 :) - Ellipsis

5

尝试使用com.google.gson.JsonParser。

        String jsonString = "object json representation";
        JsonParser jsonParser = new JsonParser();
        JsonElement jsonElement = jsonParser.parse(jsonString);

        if (jsonElement.isJsonArray()) {
            // some logic
        }

使用JsonElement实例获取对象有不同的方法,例如 - 只需使用com.google.gson.Gson方法即可:

public <T>  T fromJson(com.google.gson.JsonElement json, java.lang.Class<T> classOfT) throws com.google.gson.JsonSyntaxException 

public <T>  T fromJson(com.google.gson.JsonElement json, java.lang.reflect.Type typeOfT) throws com.google.gson.JsonSyntaxException

因此,请学习JsonElement、JsonArray、JsonPrimitive、JsonNull和JsonObject类。相信它们有足够的接口来恢复您的对象。


0
你能否尝试使用try/catch语句,首先尝试解析数组,然后回退到解析单个对象类?
你还可以进行一个非常简单的测试,查看要反序列化的字符串中第一个非空格字符,如果是“{”,则是单个对象,如果是“[”,则是数组。

我正在使用一个包含大量变量的对象来进行序列化。我正在尝试避免逐个解析变量。 - abounket
1
这些都是同一个对象,为什么对象的内部复杂性很重要,为什么你不使用gson将对象序列化,这就是为什么你正在使用gson。只需查看您尝试反序列化的字符串,如果它是有效的json,则第一个非空格字符应告诉您是否正在解析数组还是对象。 - Selecsosi
看看我的修改,也许那样会更清楚,当我不是逐个字符串地查看时。 - abounket

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