2013-05-16 3 views
12

У меня проблема с разбором ответа JSON с использованием Gson.Пользовательский десериализатор JSON с использованием Gson

JSON строку:

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

У меня есть эти 2 класса:

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. Я знаю, это потому, что первый элемент массива ответа не является объектом, а целым.

Итак, вопрос в том, могу ли я как-то его решить?

ответ

30

Вы должны написать custom deserializer. Я хотел бы сделать что-то вроде этого:

Прежде всего, необходимо включить новый класс, дальше, чем 2 у вас уже есть:

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

с этим провер oach, когда Gson пытается десериализовать JSON в класс Response, он обнаружил, что в этом классе есть атрибут response, который соответствует имени в ответе JSON, поэтому он продолжает разбор.

Тогда он осознает, что этот атрибут имеет типа VkAudioAlbumsResponse, поэтому он использует обычай десериализатор вы создали, чтобы разобрать его, который обрабатывает оставшуюся часть ответа JSON и возвращает объект VkAudioAlbumsResponse.

Примечание: Код в десериализатор довольно просто, так что я думаю, вы не будете иметь никаких проблем, чтобы это понять ... Для получения дополнительной информации см Gson API Javadoc

+0

Великого ответа, даже если я предпочитаю, чтобы создать частный метод вместо создания нового класса;) –

+1

@MattiaRuggiero Я предпочитаю отдельный класс с этой конкретной ответственностью - наличие большого количества маленьких классов всегда хорошее imo, если вы их четко определяете ... – MikO

Смежные вопросы