Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Custom JSON deserializer using Gson

I have a problem with parsing a JSON response using Gson.

JSON string:

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

I have these 2 classes:

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

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

But I have an Exception when parse this using Gson. I know this is because response array first element is not an object, but integer.

So the question is, can I solve it somehow?

like image 908
nikita.zhelonkin Avatar asked May 16 '13 14:05

nikita.zhelonkin


People also ask

How do I deserialize JSON with Gson?

Deserialization in the context of Gson means converting a JSON string to an equivalent Java object. In order to do the deserialization, we need a Gson object and call the function fromJson() and pass two parameters i.e. JSON string and expected java type after parsing is finished. Program output.

How do I read a JSON file with Gson?

Reading and writing JSON using GSON is very easy. You can use these two methods: toJSON() : It will convert simple pojo object to JSON string. FromJSON() : It will convert JSON string to pojo object.

Does Gson ignore extra fields?

As you can see, Gson will ignore the unknown fields and simply match the fields that it's able to.

What does Gson to JSON do?

Gson is a Java library that can be used to convert Java objects into their JSON representation. It can also be used to convert a JSON string to an equivalent Java object. Gson can work with arbitrary Java objects including objects for which you do not have the source.


1 Answers

You have to write a custom deserializer. I'd do something like this:

First you need to include a new class, further than the 2 you already have:

public class Response {
    public VkAudioAlbumsResponse response;
}

And then you need a custom deserializer, something similar to this:

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

Then you have to deserialize your JSON like:

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

With this approach, when Gson tries to deserialize the JSON into Response class, it finds that there is an attribute response in that class that matches the name in the JSON response, so it continues parsing.

Then it realises that this attribute is of type VkAudioAlbumsResponse, so it uses the custom deserializer you have created to parse it, which process the remaining portion of the JSON response and returns an object of VkAudioAlbumsResponse.

Note: The code into the deserializer is quite straightforward, so I guess you'll have no problem to understand it... For further info see Gson API Javadoc

like image 124
MikO Avatar answered Sep 27 '22 21:09

MikO