使用Gson自定义JSON反序列化器

13

我在使用Gson解析JSON响应时遇到了问题。

JSON字符串:

response: [
  2, {
    owner_id: 23972237,
    album_id: 25487692,
    title: 'album not new'
  }, {
    owner_id: 23972237,
    album_id: 25486631,
    title: 'фыв'
  }
]

我有这两个类:

public class VkAudioAlbumsResponse {
    public ArrayList<VkAudioAlbum> response;
    public VkError error;
}

public class VkAudioAlbum {
    public int owner_id;
    public int album_id;
    public String title;
}

但是当我使用Gson解析时,出现了一个异常。我知道这是因为响应数组的第一个元素不是对象,而是整数。

所以问题是,我能否以某种方式解决它?


你所谓的“JSON字符串”不是一个有效的JSON字符串。 - Ryan Augustine
1个回答

31

你需要编写一个自定义反序列化器。我会像这样做:

首先,你需要包含一个新的类,不同于你已有的两个类:

public class Response {
    public VkAudioAlbumsResponse response;
}

然后你需要一个自定义反序列化器,类似于这样:

private class VkAudioAlbumsResponseDeserializer 
    implements JsonDeserializer<VkAudioAlbumsResponse> {

  @Override
  public VkAudioAlbumsResponse deserialize(JsonElement json, Type type,
        JsonDeserializationContext context) throws JsonParseException {

    JsonArray jArray = (JsonArray) json;

    int firstInteger = jArray.get(0); //ignore the 1st int

    VkAudioAlbumsResponse vkAudioAlbumsResponse = new VkAudioAlbumsResponse();

    for (int i=1; i<jArray.size(); i++) {
      JsonObject jObject = (JsonObject) jArray.get(i);
      //assuming you have the suitable constructor...
      VkAudioAlbum album = new VkAudioAlbum(jObject.get("owner_id").getAsInt(), 
                                            jObject.get("album_id").getAsInt(), 
                                            jObject.get("title").getAsString());
      vkAudioAlbumsResponse.getResponse().add(album);
    }

    return vkAudioAlbumsResponse;
  }  
}

然后你需要像这样反序列化你的JSON:

GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(VkAudioAlbumsResponse.class, new VkAudioAlbumsResponseDeserializer());
Gson gson = gsonBuilder.create();
Response response = gson.fromJson(jsonString, Response.class);

使用这种方法时,当Gson尝试将JSON反序列化成Response类时,它发现该类中有一个匹配JSON响应中名称的属性response,因此它继续解析。

然后它意识到这个属性是VkAudioAlbumsResponse类型的,所以它使用您创建的自定义反序列化器来解析它,该解析器处理JSON响应的剩余部分并返回一个VkAudioAlbumsResponse对象。

注意:反序列化器中的代码非常简单,所以我想你不会有理解它的问题...更多信息请参见Gson API Javadoc


很好的答案,尽管我更喜欢创建一个私有方法而不是创建一个新类 ;) - Mattia Ruggiero
1
@MattiaRuggiero 我更喜欢一个具有特定职责的单独类 - 在我看来,拥有许多小类总是很好的,只要你清晰地组织它们... - MikO

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接