【问题标题】:Gson deserializer support multiple typesGson 解串器支持多种类型
【发布时间】:2014-10-19 11:19:58
【问题描述】:

我想反序列化 JSON 响应,但我不确定格式。在每种情况下,格式可能会有所不同。例如,响应包含一个名为“error”的字段,该字段可能为 false(布尔值)或描述错误的对象,例如。 “错误”:{“代码”:xxx,“描述”:“等”}

我应该如何实现一个涵盖这两种情况的类?有没有办法做到这一点?

谢谢

【问题讨论】:

  • 反序列化为地图和列表,然后在访问数据时检查数据。

标签: java json gson json-deserialization


【解决方案1】:

我更愿意为您的情况使用 TypeAdapter:

private static class Error {
    private boolean hasError;
    private int code;
    private String description;
}

private static class ErrorTypeAdapter extends TypeAdapter<Error> {

    @Override
    public Error read(JsonReader jsonReader) throws IOException {
        Error response = null;

        jsonReader.beginObject();

        while (jsonReader.hasNext()) {
            String currentJsonName = jsonReader.nextName();
            if("error".equals(currentJsonName)) {
                response = new Error();
                try {
                    response.hasError = jsonReader.nextBoolean();
                } catch (Exception e) {
                    response.hasError = true;
                    jsonReader.beginObject();
                }
            } else if("code".equals(currentJsonName)) {
                response.code = jsonReader.nextInt();
            } else if ("description".equals(currentJsonName)) {
                response.description = jsonReader.nextString();
            }
        }
        if(response.hasError) {
            jsonReader.endObject();
        }
        jsonReader.endObject();

        return response;
    }

    @Override
    public void write(JsonWriter jsonWriter, Error response)
            throws IOException {
        jsonWriter.beginObject();
        jsonWriter.name("hasError").value(response.hasError);
        jsonWriter.name("code").value(response.code);
        jsonWriter.name("description").value(response.description);
        jsonWriter.endObject();
    }

}

要测试它,您可以使用:

String val1 = "{\"error\": {\"code\": 1 , \"description\":\"etc\"}}";
String val2 = "{\"error\": false}";

final GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(Error.class, new ErrorTypeAdapter());
gsonBuilder.setPrettyPrinting();

final Gson gson = gsonBuilder.create();

gson.fromJson(val1, Error.class);
gson.fromJson(val2, Error.class);

您可以阅读有关 TypeAdapters 的更多信息 here 以及一些很好的示例 here

【讨论】:

  • 为什么是 'jsonReader.endObject();'叫了 2 次?
  • @ApollonDigital 如果您调试测试用例(val1 和 val2),您就会理解它。如果错误 json 值返回一个布尔值,它将是一个原始类型。但是如果错误json值返回一个code和一个desc字符串值,那它就是一个内部对象,需要一个beginObject和一个endObject。
  • 不错的一个! ...但是当响应中的“错误”为假时,我还有另一个名为“响应”的字段:{...}(在“错误”字段之后)?我可以以某种方式调用“响应”部分的默认阅读器吗?
  • @ApollonDigital 是的,你可以。您最好阅读我分享的链接并尝试理解 TypeAdapters。您将轻松实现您的目标,并对 gson 及其酷炫的功能有更好的了解。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-01-07
  • 2011-05-23
  • 1970-01-01
  • 2018-07-27
相关资源
最近更新 更多