[英]GSON - Deserialize primitive array
Consider this simple Json: 考虑一下这个简单的Json:
{
"test": [
0,
3
]
}
Now I want to deserialize it in a simple int array so for that I use a custom deserializer: 现在我想在一个简单的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);
}
}
and then: 然后:
Gson gson = new GsonBuilder().registerTypeAdapter(int[].class, new ArrayDeserializer()).create();
int[] arr = gson.fromJson(json, int[].class);
which throws: 抛出:
Exception in thread "main" com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Not a JSON Object: [0,3]
However when I do this: 但是当我这样做时:
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);
}
}
it works and I get the expected output. 它工作,我得到预期的输出。 Why?
为什么?
Let's rewrite your ArrayDeserializer
in to an equivalent form but more expressive 让我们将
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);
}
}
The JsonDeserializationContext#deserialize
javadoc states 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.永远不应该在作为
JsonDeserializer.deserialize(JsonElement, Type, JsonDeserializationContext)
方法的参数接收的元素上调用它。 Doing so will result in an infinite loop sinceGson
will in-turn call the custom deserializer again.这样做会导致无限循环,因为
Gson
会再次调用自定义反序列化器。
So, even if it had worked, you'd more than likely have a stackoverflow on your hands. 所以,即使它有效,你很可能会有一个堆栈溢出。
So why didn't it work? 那么为什么它不起作用?
You called (in pseudo-code) 你叫(伪代码)
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)
This last time you recurred, the JSON was already in the form of a JSON array but your ArrayDeserializer
was expecting a JSON object. 上一次你再次出现时,JSON已经是JSON数组的形式,但你的
ArrayDeserializer
期待一个JSON对象。
In your second attempt 在你的第二次尝试
return gson.fromJson(json.getAsJsonObject().getAsJsonArray("test"), int[].class);
you're again extracting the 'test' JSON array and feeding it to a new Gson
instance on which you haven't registered your ArrayDeserializer
. 你再次提取'
ArrayDeserializer
数组并将它提供给你尚未注册ArrayDeserializer
的新Gson
实例。 In effect, you're invoking 实际上,你正在调用
new Gson().fromJson("[0,3]", int[].class);
which is supported out of the box and will return an int[]
with the two elements 0 and 3, as expected. 它是开箱即用的,并将返回一个带有两个元素0和3的
int[]
,如预期的那样。
There are simpler solutions. 有更简单的解决方案。
Define a simple POJO type 定义一个简单的POJO类型
class Pojo {
private int[] test;
public int[] getTest() {
return test;
}
public void setTest(int[] test) {
this.test = test;
}
}
and deserialize to it 并反序列化它
Pojo pojo = new Gson().fromJson(json, Pojo.class);
int[] arr = pojo.getTest();
Or 要么
Gson gson = new Gson();
JsonArray jsonArray = gson.toJsonTree(json).getAsJsonObject().get("test").getAsJsonArray();
int[] arr = gson.fromJson(jsonArray, int[].class);
Well, looking at your desired version of ArrayDeserializer class: 好吧,看看你想要的ArrayDeserializer类的版本:
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);
}
}
Inside deserialize
method you are calling again deserialize
, so at the second call, you'll not have an array... that is the reason why you have an IllegalStateException
. 在
deserialize
方法中你再次调用deserialize
,所以在第二次调用时,你将没有数组......这就是你有一个IllegalStateException
的原因。
Your method should create an int[]
array (with the appropriate convertions) and then return it. 您的方法应该创建一个
int[]
数组(具有适当的转换),然后返回它。 That's why your second version, with gson.fromJson
works, because fromJson
deserializes to int[]
. 这就是为什么你的第二个版本,
gson.fromJson
工作,因为fromJson
反序列化为int[]
。 Maybe you keep using this to do the converting dirt work. 也许你继续用它来做转换污垢的工作。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.