且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

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

更新时间:2023-01-16 21:20:24

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

You would write a custom deserializer that returns the embedded object.

假设您的 JSON 是:

Let's say your JSON is:

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

然后你会有一个 Content POJO:

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

    }
}

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

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

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

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

You can deserialize your JSON straight to your Content:

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

编辑以从评论中添加:

如果您有不同类型的消息,但它们都有内容"字段,您可以通过执行以下操作使解串器通用:

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

    }
}

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

You just have to register an instance for each of your types:

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

当您调用 .fromJson() 时,类型会被带入反序列化器,因此它应该适用于您的所有类型.

When you call .fromJson() the type is carried into the deserializer, so it should then work for all your types.

最后在创建 Retrofit 实例时:

And finally when creating a Retrofit instance:

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