2011-01-31 2 views
4

Я изучаю использование GSON Google для моего проекта Android, который запросит JSON с моего веб-сервера. JSON вернулся будет либо ...GSON: зная, какой тип объекта нужно преобразовать?

1) Успешный ответ известного типа (например, класс "User"):

{ 
    "id":1, 
    "username":"bob", 
    "created_at":"2011-01-31 22:46:01", 
    "PhoneNumbers":[ 
     { 
      "type":"home", 
      "number":"+1-234-567-8910" 
     }, 
     { 
      "type":"mobile", 
      "number":"+1-098-765-4321" 
     } 
    ] 
} 

2.) Неудачный ответ, который всегда будет взять на себя одна и та же базовая структура ниже.

{ 
    "error":{ 
     "type":"Error", 
     "code":404, 
     "message":"Not Found" 
    } 
} 

Я хотел бы GSON преобразовать к нужному типу в зависимости от наличия пары error ключ/значение выше. Самый практичный способ, который я могу сделать, состоит в следующем, но мне любопытно, есть ли лучший способ.

final String response = client.get("http://www.example.com/user.json?id=1"); 
final Gson gson = new Gson(); 

try { 
    final UserEntity user = gson.fromJson(response, UserEntity.class); 
    // do something with user 
} catch (final JsonSyntaxException e) { 
    try { 
     final ErrorEntity error = gson.fromJson(response, ErrorEntity.class); 
     // do something with error 
    } catch (final JsonSyntaxException e) { 
     // handle situation where response cannot be parsed 
    } 
} 

Это действительно просто псевдокод, хотя, потому что в первом состоянии поймать, я не знаю, как проверить, существует ли ключ error в ответ JSON. Поэтому я думаю, что мой вопрос двоякий:

  1. Могу ли я/как использовать GSON для проверки существования ключа и принять решение о том, как на нем разбираться?
  2. Это то, что другие в подобной ситуации делают с GSON, или есть лучший способ?

ответ

5

Что вы обычно хотели бы сделать, так это вернуть серверу реальный код ошибки вместе с ответом об ошибке JSON. Затем вы читаете ответ как ErrorEntity, если вы получите код ошибки и как UserEntity, если вы получите 200. Очевидно, для этого требуется немного больше иметь дело с деталями связи с сервером, чем просто превращать URL-адрес в строку, но это как это.

Это говорит о том, что другой вариант заключается в использовании пользовательского JsonDeserializer и класса, который может возвращать либо значение, либо ошибку.

public class ValueOrErrorDeserializer<V> implements JsonDeserializer<ValueOrError<V>> { 
    public ValueOrError<V> deserialize(JsonElement json, Type typeOfT, 
            JsonDeserializationContext context) { 
    JsonObject object = json.getAsJsonObject(); 
    JsonElement error = object.get("error"); 
    if (error != null) { 
     ErrorEntity entity = context.deserialize(error, ErrorEntity.class); 
     return ValueOrError.<V>error(entity); 
    } else { 
     Type valueType = ((ParameterizedType) typeOfT).getActualTypeArguments()[0]; 
     V value = (V) context.deserialize(json, valueType); 
     return ValueOrError.value(value); 
    } 
    } 
} 

Вы бы тогда быть в состоянии сделать что-то вроде этого:

String response = ... 
ValueOrError<UserEntity> valueOrError = gson.fromJson(response, 
    new TypeToken<ValueOrError<UserEntity>>(){}.getType()); 
if (valueOrError.isError()) { 
    ErrorEntity error = valueOrError.getError(); 
    ... 
} else { 
    UserEntity user = valueOrError.getValue(); 
    ... 
} 

Я не пробовал этот код, и я бы еще рекомендовал использовать код ошибки HTTP, но это дает вы пример того, как вы можете использовать JsonDeserializer, чтобы решить, что делать с некоторыми JSON.

+0

Изменение кода ошибки должно быть простым в том, как настроено мое веб-приложение. Мне придется поиграть и выяснить, удалит ли ключ «ошибка» в результате JSON или что-то вроде выше, будет лучше для меня. Огромное спасибо за ваш подробный ответ, я очень ценю это! –

+0

Чтобы следить за тем, чтобы мой веб-сервер не возвращал статус HTTP 200 всякий раз, когда ожидается ответ об ошибке, и я изменил ответ на ошибку JSON, чтобы не включать в себя инкапсулирующую клавишу «ошибка», включая только «тип», код "и" сообщение ". Сейчас все работает так, как хотелось бы. Спасибо за помощь! –

+0

Практически, но JsonDeserializer - это интерфейс, поэтому вам нужно его реализовать, а не расширять. –

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