java 使用 GSON 解析多类型数组
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5377827/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Using GSON to parse array with multiple types
提问by Fofx
I wish to use GSON to parse the following json:
我希望使用 GSON 来解析以下 json:
[
[
"hello",
1,
[2]
],
[
"world",
3,
[2]
]
]
So, that's 1 array, containing 2 arrays. The 2 inner arrays are themselves arrays, comprised of String, int, array types.
所以,这是 1 个数组,包含 2 个数组。2 个内部数组本身就是数组,由 String、int、数组类型组成。
I'm unsure how I can using Java classes to model the array which has 3 different types (String, int, array). I start with:
我不确定如何使用 Java 类对具有 3 种不同类型(字符串、整数、数组)的数组进行建模。我开始:
// String json just contains the aforementioned json string.
ArrayList<ArrayList<XXX>> data = new ArrayList<ArrayList<XXX>>();
Type arrayListType = new TypeToken<ArrayList<ArrayList<XXX>>>(){}.getType();
data = gson.fromJson(json, arrayListType);
But what should be where the 'XXX' are? I think it should be an array, but it should be an array with 3 different data types. So how can I use Java to model this?
但是“XXX”应该在哪里?我认为它应该是一个数组,但它应该是一个具有 3 种不同数据类型的数组。那么我如何使用 Java 来建模呢?
Can any help? Thank you.
有什么帮助吗?谢谢你。
回答by Programmer Bruce
Gson has special handling for deserializing some single-component arrays into a non-array type. For example, int data = gson.fromJson("[3]", int.class);
would assign the int value 3 to data.
Gson 具有将一些单组件数组反序列化为非数组类型的特殊处理。例如,int data = gson.fromJson("[3]", int.class);
将 int 值 3 分配给数据。
Of course, deserializing a single-component array into a non-array type is not required. For example, the previous example could be deserialized as int[] data = gson.fromJson("[3]", int[].class);
.
当然,不需要将单组件数组反序列化为非数组类型。例如,前面的示例可以反序列化为int[] data = gson.fromJson("[3]", int[].class);
.
Gson will also often deserialize a non-String value into a String, when asked. Applying this to the first example, String data = gson.fromJson("[3]", String.class);
works just as well.
当被询问时,Gson 也经常将非字符串值反序列化为字符串。将此应用于第一个示例,String data = gson.fromJson("[3]", String.class);
效果也一样。
Note that it does not work to tell Gson to deserialize the first example as type Object. Object data = gson.fromJson("[3]", Object.class);
results in a parse exception complaining that [3] is not a primitive.
请注意,告诉 Gson 将第一个示例反序列化为 Object 类型是行不通的。 Object data = gson.fromJson("[3]", Object.class);
导致解析异常,抱怨 [3] 不是原语。
Applied to the example in the original question above, if it's acceptable to treat all of the values as Strings, then deserialization becomes simple.
应用于上面原始问题中的示例,如果将所有值都视为字符串是可以接受的,那么反序列化就变得简单了。
// 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();
}
}
}
Unfortunately, with Gson I've not been able to figure out a simple deserialization approach that would allow for "better" binding to more specific and mixed types in an array, since Java doesn't provide a syntax for defining a mixed type array. For example, the preferred type of the collection in the original question might be List<List<String, int, List<int>>>
, but that's not possible to define in Java. So, you gotta be content with List<List<String>> (or String[][])
, or turn to an approach with more "manual" parsing.
不幸的是,对于 Gson,我无法找出一种简单的反序列化方法,该方法可以“更好地”绑定到数组中更具体的混合类型,因为 Java 不提供定义混合类型数组的语法。例如,原始问题中集合的首选类型可能是List<List<String, int, List<int>>>
,但这不可能在 Java 中定义。因此,您必须满足于List<List<String>> (or String[][])
,或者转向具有更多“手动”解析的方法。
(Yes, Java allows a type declaration of List<List<Object>>
, but Object
is not a specific enough type to meaningfully deserialize to. Also, as discussed, attempting to deserialize [3] to Object results in a parse exception.)
(是的,Java 允许 的类型声明List<List<Object>>
,但Object
不是一个足够具体的类型来有意义地反序列化。此外,正如所讨论的,尝试将 [3] 反序列化为 Object 会导致解析异常。)
Small Update: I recently had to deserialize some sloppy JSON that included a structure not too dissimilar from that in the original question. I ended up just using a custom deserializer to create a object from the messy JSON array. Similar to the following example.
小更新:我最近不得不反序列化一些草率的 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<MyThreeThings>
{
@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);
}
}
The Gson user guide does cover handling deserialization of collections of mixed types with a similar example as this in the "Serializing and Deserializing Collection with Objects of Arbitrary Types" section.
Gson 用户指南确实涵盖了处理混合类型集合的反序列化,其中包含与“使用任意类型的对象序列化和反序列化集合”部分中的类似示例。
回答by uvesten
First, I think you may be mistaken in your example above. An Array consisting of three different is a very unusual approach, to say the least. Probably your json structure is an array, containing tuples. These tuples then include an array.
首先,我认为您在上面的示例中可能有误。至少可以说,由三个不同的数组组成的数组是一种非常不寻常的方法。可能您的 json 结构是一个包含元组的数组。这些元组然后包含一个数组。
Like:
喜欢:
[
{
"hello",
1,
[2]
},
{
"world",
3,
[2]
}
]
XXX should be an object containing:
XXX 应该是一个包含以下内容的对象:
A String
一个字符串
An int (or Integer)
一个整数(或整数)
An Array of (I guess) ints.
一个(我猜)整数数组。
Then you make an array of these objects and parse the json into it.
然后你创建一个这些对象的数组并将 json 解析成它。
However, your json seems really badly formed, since all members should be named, like
然而,你的 json 似乎真的很糟糕,因为所有成员都应该被命名,比如
[
{
"str":"hello",
"intVal":1,
"intArr":[2]
},
{
"str":"world",
"intVal":3,
"intArr":[2]
}
]
If, on the other hand, the JSON really looks the way you describe it, you would have to make arrays of Object, plain and simple, and then cast them when you read them from your data structure.
另一方面,如果 JSON 看起来真的像你描述的那样,你就必须制作 Object 数组,简单明了,然后在你从你的数据结构中读取它们时转换它们。