使用GSON解析具有多种类型的数组

我希望使用GSON来解析以下json:

[ [ "hello", 1, [2] ], [ "world", 3, [2] ] ] 

那么,这是1个数组,包含2个数组。 2个内部数组本身就是数组,由String,int,数组类型组成。

我不确定如何使用Java类来建模具有3种不同类型(String,int,array)的数组。 我从:

 // String json just contains the aforementioned json string. ArrayList<ArrayList> data = new ArrayList<ArrayList>(); Type arrayListType = new TypeToken<ArrayList<ArrayList>>(){}.getType(); data = gson.fromJson(json, arrayListType); 

但是’XXX’应该在哪里? 我认为它应该是一个数组,但它应该是一个包含3种不同数据类型的数组。 那么我该如何使用Java来建模呢?

有什么帮助吗? 谢谢。

Gson对将一些单组件数组反序列化为非数组类型进行了特殊处理。 例如, int data = gson.fromJson("[3]", int.class); 将int值3分配给数据。

当然,不需要将单组件arrays反序列化为非数组类型。 例如,前面的示例可以反序列化为int[] data = gson.fromJson("[3]", int[].class);

当被问及时,Gson还经常将非String值反序列化为String。 将此应用于第一个示例, String data = gson.fromJson("[3]", String.class); 同样有效。

请注意,告诉Gson将第一个示例反序列化为Object类型并不起作用。 Object data = gson.fromJson("[3]", Object.class); 导致一个解析exception抱怨[3]不是原始的。

应用于上述原始问题中的示例,如果将所有值视为字符串是可接受的,则反序列化变得简单。

 // output: // hello 1 2 // world 3 2 public class Foo { static String jsonInput = "[" + "[\"hello\",1,[2]]," + "[\"world\",3,[2]]" + "]"; public static void main(String[] args) { Gson gson = new Gson(); String[][] data = gson.fromJson(jsonInput, String[][].class); for (String[] data2 : data) { for (String data3 : data2) { System.out.print(data3); System.out.print(" "); } System.out.println(); } } } 

不幸的是,对于Gson,我无法找到一种简单的反序列化方法,它允许“更好”地绑定到数组中更具体和混合的类型,因为Java没有提供定义混合类型数组的语法。 例如,原始问题中的首选集合类型可能是List>> ,但这不可能在Java中定义。 因此,您必须满足于List> (or String[][]) ,或转向具有更多“手动”解析的方法。

(是的,Java允许List>的类型声明,但是Object不是一个特定的类型,无法有意义地反序列化。另外,正如所讨论的,尝试将[3]反序列化为Object会导致解析exception。)


小更新:我最近不得不反序化一些草率的JSON,其中包含的结构与原始问题中的结构不太相似。 我最后只使用自定义反序列化器从凌乱的JSON数组中创建一个对象。 与以下示例类似。

 // output: // [{MyThreeThings: first=hello, second=1, third=[2]}, // {MyThreeThings: first=world, second=3, third=[4, 5]}] import java.lang.reflect.Type; import java.util.Arrays; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.JsonArray; import com.google.gson.JsonDeserializationContext; import com.google.gson.JsonDeserializer; import com.google.gson.JsonElement; import com.google.gson.JsonParseException; public class FooToo { static String jsonInput = "[" + "[\"hello\",1,[2]]," + "[\"world\",3,[4,5]]" + "]"; public static void main(String[] args) { GsonBuilder gsonBuilder = new GsonBuilder(); gsonBuilder.registerTypeAdapter(MyThreeThings.class, new MyThreeThingsDeserializer()); Gson gson = gsonBuilder.create(); MyThreeThings[] things = gson.fromJson(jsonInput, MyThreeThings[].class); System.out.println(Arrays.toString(things)); } } class MyThreeThings { String first; int second; int[] third; MyThreeThings(String first, int second, int[] third) { this.first = first; this.second = second; this.third = third; } @Override public String toString() { return String.format( "{MyThreeThings: first=%s, second=%d, third=%s}", first, second, Arrays.toString(third)); } } class MyThreeThingsDeserializer implements JsonDeserializer { @Override public MyThreeThings deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { JsonArray jsonArray = json.getAsJsonArray(); String first = jsonArray.get(0).getAsString(); int second = jsonArray.get(1).getAsInt(); JsonArray jsonArray2 = jsonArray.get(2).getAsJsonArray(); int length = jsonArray2.size(); int[] third = new int[length]; for (int i = 0; i < length; i++) { int n = jsonArray2.get(i).getAsInt(); third[i] = n; } return new MyThreeThings(first, second, third); } } 

Gson用户指南确实涵盖了处理混合类型集合的反序列化,其示例与“使用任意类型的对象进行序列化和反序列化集合”部分中的类似示例相同。

首先,我认为你可能在上面的例子中弄错了。 至少可以说,由三种不同组成的arrays是一种非常不寻常的方法。 可能你的json结构是一个包含元组的数组。 然后这些元组包括一个数组。

喜欢:

 [ { "hello", 1, [2] }, { "world", 3, [2] } ] 

XXX应该是包含以下内容的对象:

一个字符串

一个int(或整数)

一个(我猜)int的数组。

然后你创建这些对象的数组并将json解析为它。

但是,你的json似乎非常糟糕,因为所有的成员都应该被命名,就像

 [ { "str":"hello", "intVal":1, "intArr":[2] }, { "str":"world", "intVal":3, "intArr":[2] } ] 

另一方面,如果JSON真的看起来像你描述的那样,那么你必须创建简单的Object数组,然后在从数据结构中读取它们时抛出它们。