GSON:知道要转换为什么类型的对象?

时间:2011-01-31 04:54:15

标签: java json gson

我正在考虑使用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
    }
}

这实际上只是伪代码,因为在第一个catch条件中,我不确定如何测试JSON响应中是否存在密钥error。所以我想我的问题是双重的:

  1. 我可以/我如何使用GSON来测试密钥的存在,并根据它来决定如何解析?
  2. 这是其他处于类似情况的人正在使用GSON,还是有更好的方法?

1 个答案:

答案 0 :(得分:5)

您通常要做的是让您的服务器返回实际的错误代码以及JSON错误响应。然后,如果您收到错误代码,则将响应读作ErrorEntity;如果得到错误代码,则将其读作UserEntity。显然,这需要更多地处理与服务器通信的细节,而不仅仅是URL中的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。