GSON: зная, какой тип объекта конвертировать? - PullRequest
4 голосов
/ 31 января 2011

Я использую Google GSON для моего проекта Android, который будет запрашивать JSON с моего веб-сервера.Возвращенный JSON будет либо ...

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

{
    "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 для проверки существования ключа и принять решение о том, как выполнить анализ на основе этого?* Это то, что другие в подобной ситуации делают с GSON, или есть лучший способ?

1 Ответ

5 голосов
/ 31 января 2011

Обычно вы хотите, чтобы ваш сервер возвращал реальный код ошибки вместе с ответом на ошибку 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.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...