GSON: knowing what type of object you need to convert?

I am learning Google GSON for my Android project, which will request JSON from my web server. The returned JSON will be either ...

1) A successful response of a known type (for example, the class "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.) An unsuccessful answer that will always have the same basic structure below.

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

I would like GSON to convert to the correct type depending on the presence of the error key / value pair above. The most practical way I can do is as follows, but I'm curious if there is a better way.

 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 } } 

This is really just pseudo code, though, since in the first catch state I am not sure how to check if the error key exists in the JSON response. Therefore, I think my question is twofold:

  • Can I / how can I use GSON to verify the key exists and decide how to understand it?
  • Is this what others in a similar situation do with GSON, or is there a better way?
+4
source share
1 answer

What you usually want to do is return a real error code to the server along with a JSON error response. Then you read the answer as ErrorEntity if you get an error code and as UserEntity if you get 200. Obviously, this requires a bit more work with the details of communication with the server than just turning the URL into a String, but that's how.

However, I believe that another option is to use a custom JsonDeserializer and a class that can return either a value or an error.

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

Then you can do something like this:

 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(); ... } 

I have not tried this code, and I still recommend using the HTTP error code, but it gives you an example of how you can use the JsonDeserializer to decide what to do with some JSON.

+5
source

Source: https://habr.com/ru/post/1337718/


All Articles