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

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

问题是我所有的POJO都有status,reason个字段,content字段里面是我想要的真正的POJO.

有没有办法创建一个自定义的gson转换器来提取始终为content的字段,以便REVERATION返回适当的POJO?

推荐答案

您将编写一个返回嵌入对象的自定义反序列化程序.

假设你的JSON是:

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

You'd then have a Content POJO:

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

    }
}

Now if you construct a Gson with GsonBuilder and register the deserializer:

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

您可以直接将JSON反序列化到Content:

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

Edit to add from comments:

If you have different types of messages but they all have the "content" field, you can make the Deserializer generic by doing:

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

Json相关问答推荐

当有嵌套数组而没有嵌套数组时,展平JSON

删除JSON文件的特定内容

JOLT分裂和数组数据

具有 (RegEx) 模式的 json-schema 中的枚举

遍历 JSON,检索父值

Oracle json 对象的最后一个值不在引号中

用powershell条件解析json文件的数组对象

根据数据框中的其他列值将列表 json 对象插入行

如何将从嵌套 Select 返回的空值转换为空数组?

使用 jq 将键值行转换为 json

将嵌套的 JSON 对象规范化为 Pandas 数据框

以 JSON 格式访问(新型、公共)Google 工作表

Play Framework:如何序列化/反序列化与 JSON 的枚举

现代浏览器一次可以处理多少个 HTML 元素?

反序列化大型 json 对象的 JsonMaxLength 异常

jQuery.getJSON 和 jQuery.parseJSON 返回 [object Object]?

gson:将 null 视为空字符串

Django:TypeError:[] 不是 JSON 可序列化的为什么?

如何将单引号转义成双引号转成单引号

从 JSON 到 JSONL 的 Python 转换