java – GSON – 反序列化原始数组

考虑一下这个简单的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 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.

所以,即使它有效,你很可能会有一个堆栈溢出.

那么为什么它不起作用?

你叫(伪代码)

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);

它是开箱即用的,并将返回一个带有两个元素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);

转载注明原文:java – GSON – 反序列化原始数组 - 代码日志