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

Mat*_*ins 4 java json gson

我正在考虑将Google的GSON用于我的Android项目,该项目将从我的Web服务器请求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"
        }
    ]
}
Run Code Online (Sandbox Code Playgroud)

2.)不成功的响应,它将始终采用相同的基本结构.

{
    "error":{
        "type":"Error",
        "code":404,
        "message":"Not Found"
    }
}
Run Code Online (Sandbox Code Playgroud)

我希望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
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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

Col*_*inD 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);
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

然后你就可以做这样的事情:

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();
  ...
}
Run Code Online (Sandbox Code Playgroud)

我没有尝试过该代码,我仍然建议使用HTTP错误代码,但它给出了一个示例,说明如何使用a JsonDeserializer来决定如何处理某些JSON.