我正在使用Android应用程序中的API,所有JSON响应均如下所示:
{ 'status': 'OK', 'reason': 'Everything was fine', 'content': { < some data here > }
问题是,我所有的POJO有status,reason字段,里面content领域是真正的POJO我想要的。
status
reason
content
有什么方法可以创建Gson的自定义转换器以始终提取content字段,因此改造会返回适当的POJO?
您将编写一个自定义反序列化器,该反序列化器返回嵌入的对象。
假设您的JSON是:
{ "status":"OK", "reason":"some reason", "content" : { "foo": 123, "bar": "some value" } }
然后,您将获得一个ContentPOJO:
Content
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
GsonBuilder
Gson gson = new GsonBuilder() .registerTypeAdapter(Content.class, new MyDeserializer()) .create();
您可以直接将JSON反序列化为Content:
Content c = gson.fromJson(myJson, Content.class);
编辑以添加评论:
如果您有不同类型的消息,但是它们都具有“ content”字段,则可以通过执行以下操作使反序列化器通用:
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()该类型时,该类型将携带到反序列化器中,因此它应适用于所有类型。
.fromJson()
最后,在创建Retrofit实例时:
Retrofit retrofit = new Retrofit.Builder() .baseUrl(url) .addConverterFactory(GsonConverterFactory.create(gson)) .build();