GSON - 反序列化原始数组
GSON - Deserialize primitive array
考虑这个简单的问题 Json:
{
"test": [
0,
3
]
}
现在我想在一个简单的 int 数组中反序列化它,为此我使用自定义反序列化器:
class ArrayDeserializer implements JsonDeserializer<int[]> {
@Override
public int[] deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
return context.deserialize(json.getAsJsonObject().getAsJsonArray("test"), int[].class);
}
}
然后:
Gson gson = new GsonBuilder().registerTypeAdapter(int[].class, new ArrayDeserializer()).create();
int[] arr = gson.fromJson(json, int[].class);
抛出:
Exception in thread "main" com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Not a JSON Object: [0,3]
但是当我这样做时:
class ArrayDeserializer implements JsonDeserializer<int[]> {
private static final Gson gson = new Gson();
@Override
public int[] deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
return gson.fromJson(json.getAsJsonObject().getAsJsonArray("test"), int[].class);
}
}
它有效,我得到了预期的输出。为什么?
嗯,看看你想要的 ArrayDeserializer 版本 class:
class ArrayDeserializer implements JsonDeserializer<int[]> {
@Override
public int[] deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
return context.deserialize(json.getAsJsonObject().getAsJsonArray("test"), int[].class);
}
}
在 deserialize
方法中你再次调用 deserialize
,所以在第二次调用时,你不会有一个数组...这就是为什么你有一个 IllegalStateException
.
您的方法应该创建一个 int[]
数组(具有适当的转换),然后 return 它。这就是为什么你的第二个版本 gson.fromJson
有效,因为 fromJson
反序列化为 int[]
。也许你一直用它来做转换的污垢工作。
让我们将您的 ArrayDeserializer
重写为等效但更具表现力的形式
class ArrayDeserializer implements JsonDeserializer<int[]> {
@Override
public int[] deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
JsonArray jsonArray = json.getAsJsonObject().getAsJsonArray("test");
return context.deserialize(jsonArray, int[].class);
}
}
JsonDeserializationContext#deserialize
javadoc 声明
Invokes default deserialization on the specified object. It should
never be invoked on the element received as a parameter of the
JsonDeserializer.deserialize(JsonElement, Type,
JsonDeserializationContext)
method. Doing so will result in an
infinite loop since Gson
will in-turn call the custom deserializer
again.
所以,即使它成功了,你也很可能手上有一个 Whosebug。
那么为什么它不起作用?
您调用了(伪代码)
deserialize {test:[0,3]} as int[]
// --> Gson finds ArrayDeserializer mapped to int[]
take given JSON as an object (OK), extract 'test' as JSON array (OK)
deserialize [0,3] as int[]
// --> Gson finds ArrayDeserializer mapped to int[]
take given JSON as an object (FAIL)
你上次重复出现时,JSON 已经是 JSON 数组的形式,但你的 ArrayDeserializer
需要一个 JSON 对象。
第二次尝试
return gson.fromJson(json.getAsJsonObject().getAsJsonArray("test"), int[].class);
您再次提取 'test' JSON 数组并将其提供给您尚未注册 ArrayDeserializer
的新 Gson
实例。实际上,您正在调用
new Gson().fromJson("[0,3]", int[].class);
这是开箱即用的支持,将 return 一个带有两个元素 0 和 3 的 int[]
,正如预期的那样。
有更简单的解决方案。
定义一个简单的 POJO 类型
class Pojo {
private int[] test;
public int[] getTest() {
return test;
}
public void setTest(int[] test) {
this.test = test;
}
}
并反序列化它
Pojo pojo = new Gson().fromJson(json, Pojo.class);
int[] arr = pojo.getTest();
或
Gson gson = new Gson();
JsonArray jsonArray = gson.toJsonTree(json).getAsJsonObject().get("test").getAsJsonArray();
int[] arr = gson.fromJson(jsonArray, int[].class);
考虑这个简单的问题 Json:
{
"test": [
0,
3
]
}
现在我想在一个简单的 int 数组中反序列化它,为此我使用自定义反序列化器:
class ArrayDeserializer implements JsonDeserializer<int[]> {
@Override
public int[] deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
return context.deserialize(json.getAsJsonObject().getAsJsonArray("test"), int[].class);
}
}
然后:
Gson gson = new GsonBuilder().registerTypeAdapter(int[].class, new ArrayDeserializer()).create();
int[] arr = gson.fromJson(json, int[].class);
抛出:
Exception in thread "main" com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Not a JSON Object: [0,3]
但是当我这样做时:
class ArrayDeserializer implements JsonDeserializer<int[]> {
private static final Gson gson = new Gson();
@Override
public int[] deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
return gson.fromJson(json.getAsJsonObject().getAsJsonArray("test"), int[].class);
}
}
它有效,我得到了预期的输出。为什么?
嗯,看看你想要的 ArrayDeserializer 版本 class:
class ArrayDeserializer implements JsonDeserializer<int[]> {
@Override
public int[] deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
return context.deserialize(json.getAsJsonObject().getAsJsonArray("test"), int[].class);
}
}
在 deserialize
方法中你再次调用 deserialize
,所以在第二次调用时,你不会有一个数组...这就是为什么你有一个 IllegalStateException
.
您的方法应该创建一个 int[]
数组(具有适当的转换),然后 return 它。这就是为什么你的第二个版本 gson.fromJson
有效,因为 fromJson
反序列化为 int[]
。也许你一直用它来做转换的污垢工作。
让我们将您的 ArrayDeserializer
重写为等效但更具表现力的形式
class ArrayDeserializer implements JsonDeserializer<int[]> {
@Override
public int[] deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
JsonArray jsonArray = json.getAsJsonObject().getAsJsonArray("test");
return context.deserialize(jsonArray, int[].class);
}
}
JsonDeserializationContext#deserialize
javadoc 声明
Invokes default deserialization on the specified object. It should never be invoked on the element received as a parameter of the
JsonDeserializer.deserialize(JsonElement, Type, JsonDeserializationContext)
method. Doing so will result in an infinite loop sinceGson
will in-turn call the custom deserializer again.
所以,即使它成功了,你也很可能手上有一个 Whosebug。
那么为什么它不起作用?
您调用了(伪代码)
deserialize {test:[0,3]} as int[]
// --> Gson finds ArrayDeserializer mapped to int[]
take given JSON as an object (OK), extract 'test' as JSON array (OK)
deserialize [0,3] as int[]
// --> Gson finds ArrayDeserializer mapped to int[]
take given JSON as an object (FAIL)
你上次重复出现时,JSON 已经是 JSON 数组的形式,但你的 ArrayDeserializer
需要一个 JSON 对象。
第二次尝试
return gson.fromJson(json.getAsJsonObject().getAsJsonArray("test"), int[].class);
您再次提取 'test' JSON 数组并将其提供给您尚未注册 ArrayDeserializer
的新 Gson
实例。实际上,您正在调用
new Gson().fromJson("[0,3]", int[].class);
这是开箱即用的支持,将 return 一个带有两个元素 0 和 3 的 int[]
,正如预期的那样。
有更简单的解决方案。
定义一个简单的 POJO 类型
class Pojo {
private int[] test;
public int[] getTest() {
return test;
}
public void setTest(int[] test) {
this.test = test;
}
}
并反序列化它
Pojo pojo = new Gson().fromJson(json, Pojo.class);
int[] arr = pojo.getTest();
或
Gson gson = new Gson();
JsonArray jsonArray = gson.toJsonTree(json).getAsJsonObject().get("test").getAsJsonArray();
int[] arr = gson.fromJson(jsonArray, int[].class);