0

我正在尝试使用 Gson 和 Retrofit2 获取 POJO 实例。

典型的 JSON 响应如下所示

我的问题在于该Infobox领域。在某些情况下,(像这样)该字段将是以下类型的对象,否则为空字符串。

class Infobox {
    public List<Content> content = new ArrayList<>();
    public List<Metum> meta;
}

class Content {
    public String dataType;
    public String value;
    public String label;
    public Integer wikiOrder;
}

class Metum {
    public String dataType;
    public String value;
    public String label;
}

我试着写一个 TypeAdapter 如下

class InfoboxAdapter extends TypeAdapter<Infobox> {
    final Gson embedded = new Gson();

    @Override
    public void write(JsonWriter out, Infobox infobox) throws IOException {
        if (infobox == null) {
            out.nullValue();
            return;
        }
        out.beginObject();
        out.name("content");
        embedded.toJson(embedded.toJsonTree(infobox.content), out);

        out.name("meta");
        embedded.toJson(embedded.toJsonTree(infobox.meta), out);
        out.endObject();
    }

    @Override
    public Infobox read(JsonReader in) throws IOException {
        if ("".equals(in.peek())) {
            return null;
        }

        return embedded.fromJson(in, Infobox.class);
    }

但它失败了java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING

更令人困惑的事实是,meta响应中的字段也是一个对象,在某些情况下,其值为 null(而不是像 那样的空字符串infobox

我希望能够使用 Gson 来完成它,因为我已经将它用于其他所有内容,并且我不想添加另一个依赖项

4

2 回答 2

0

嗨,请访问: http: //www.jsonschema2pojo.org/ 粘贴您的代码。该站点会自动创建您所有相关的课程。

如果有问题,请查看此链接。

我的驱动链接

于 2016-07-14T07:09:37.520 回答
0

我最终使用了JsonDeserializer。谷歌建议:

新的应用程序应该更喜欢 TypeAdapter,它的流式 API 比这个接口的树形 API 更高效。

但我没有注意到对我的使用有任何性能影响。有一天我可能会重写它以使用 TypeAdapter,但这对我有用直到那时

class InfoboxDeserialiser implements JsonDeserializer<Infobox> {

    @Override
    public Infobox deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {

        try {
            if (json.isJsonNull() || json.isJsonPrimitive()) {
                return null;
            }

            JsonObject jsonObject = json.getAsJsonObject();

            Infobox infobox = new Infobox();

            JsonArray jsonContent = jsonObject.get("content").getAsJsonArray();
            JsonArray jsonMeta = jsonObject.get("meta").getAsJsonArray();

            infobox.content = new Content[jsonContent.size()];
            for (int i = 0; i < jsonContent.size(); i++) {
                infobox.content[i] = context.deserialize(jsonContent.get(i), Content.class);
            }

            infobox.meta = new Metum[jsonMeta.size()];
            for (int i = 0; i < jsonMeta.size(); i++) {
                infobox.meta[i] = context.deserialize(jsonContent.get(i), Metum.class);
            }

            return infobox;
        } catch (Exception e) {
            Timber.e(e, "Failed to deserialise the infobox");
            return null;
        }
    }
}

其中类如下

class Metum {
    public String dataType;
    public String value;
    public String label;
}

class Content {
    public String dataType;
    public String value;
    public String label;
    public Integer wikiOrder;
}

我在创建服务对象时注册了这个反序列化器

GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(Infobox.class, new InfoboxDeserialiser());
GsonConverterFactory converterFactory = GsonConverterFactory.create(gsonBuilder.create());
        Retrofit.Builder builder = new Retrofit.Builder()
        .baseUrl("https://api.duckduckgo.com/")
        .addConverterFactory(converterFactory);
于 2016-07-17T17:33:50.693 回答