一尘不染

Java使用改造使用GSON获取嵌套的JSON对象

java

我正在使用Android应用程序中的API,所有JSON响应均如下所示:

{
    'status': 'OK',
    'reason': 'Everything was fine',
    'content': {
         < some data here >
}

问题是,我所有的POJO有statusreason字段,里面content领域是真正的POJO我想要的。

有什么方法可以创建Gson的自定义转换器来提取始终的content字段,因此改造会返回适当的POJO?


阅读 293

收藏
2020-03-04

共1个答案

一尘不染

你将编写一个自定义反序列化器,以返回嵌入式对象。

假设你的JSON是:

{
    "status":"OK",
    "reason":"some reason",
    "content" : 
    {
        "foo": 123,
        "bar": "some value"
    }
}

然后,你将获得一个ContentPOJO:

class Content
{
    public int foo;
    public String bar;
}

然后编写一个反序列化器:

class MyDeserializer implements JsonDeserializer<Content>
{
    @Override
    public Content deserialize(JsonElement je, Type type, JsonDeserializationContext jdc)
        throws JsonParseException
    {
        // Get the "content" element from the parsed JSON
        JsonElement content = je.getAsJsonObject().get("content");

        // Deserialize it. You use a new instance of Gson to avoid infinite recursion
        // to this deserializer
        return new Gson().fromJson(content, Content.class);

    }
}

现在,如果你构造一个Gsonwith GsonBuilder并注册反序列化器:

Gson gson = 
    new GsonBuilder()
        .registerTypeAdapter(Content.class, new MyDeserializer())
        .create();

你可以将JSON直接反序列化为Content:

Content c = gson.fromJson(myJson, Content.class);

编辑以添加评论:

如果你有不同类型的消息,但是它们都有“ content”字段,则可以通过执行以下操作使Deserializer通用:

class MyDeserializer<T> implements JsonDeserializer<T>
{
    @Override
    public T deserialize(JsonElement je, Type type, JsonDeserializationContext jdc)
        throws JsonParseException
    {
        // Get the "content" element from the parsed JSON
        JsonElement content = je.getAsJsonObject().get("content");

        // Deserialize it. You use a new instance of Gson to avoid infinite recursion
        // to this deserializer
        return new Gson().fromJson(content, type);

    }
}

你只需为每种类型注册一个实例:

Gson gson = 
    new GsonBuilder()
        .registerTypeAdapter(Content.class, new MyDeserializer<Content>())
        .registerTypeAdapter(DiffContent.class, new MyDeserializer<DiffContent>())
        .create();

当你调用.fromJson()该类型时,该类型将携带到反序列化器中,因此它应适用于所有类型。

最后,在创建改造实例时:

Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(url)
                .addConverterFactory(GsonConverterFactory.create(gson))
                .build();
2020-03-04