Reputation: 1
I created a class which encapsulates the gson serialize/deserialize behaviors. The idea is to make the class totally generic, so this can be used by any part of the software that needs it.
public class JsonParser {
private static final Logger log = Logger.getLogger(JsonParser.class.getName());
private static final Gson gson = new Gson();
public static String convertToJson(Object object) {
String result = gson.toJson(object);
log.log(Level.INFO, "Result: {0}", result);
return result;
}
public static <T extends Object> T convertToString(String jsonString, Class<T> object) {
Type type = new TypeToken<T>() {}.getType();
T result = gson.fromJson(jsonString, type);
log.log(Level.INFO, "Result: {0}", result.toString());
return result;
}
}
I'm having a problem in the deserialization (method convertToString). The line: T result = gson.fromJson(jsonString, type); is throwing this error at compile time:
"type parameters of T cannot be determined; no unique maximal instance exists for type variable T with upper bounds T,java.lang.Object"
I understand this means the code is too vague and unsafe in resume. Before this version I was passing the argument named object instead of the variable type but the problem was that the returned object had problems and threw NullPointerException later in the code's execution. I readed about the problems with Gson and Generic Types so I got into the actual version.
Just in case, this is the call to the problematic method (response is a String):
JsonParser.convertToString(response, Response.class);
So the question is: How can I make this compile and keep my method generic in the intent?
Upvotes: 0
Views: 168
Reputation: 14678
Don't create type token in your utility method:
Type type = new TypeToken<T>() {}.getType();
Let caller create it for you:
public static <T> T convertToString(String jsonString, TypeToken<T> typeToken)
T result = gson.fromJson(jsonString, typeToken.getType());
log.log(Level.INFO, "Result: {0}", result.toString());
return result;
}
Example:
class Pojo {
private String field1;
private int field2;
@Override
public String toString() {
return "Pojo [field1=" + field1 + ", field2=" + field2 + "]";
}
}
List<Pojo> list = convertToString("[{\"field1\":\"abc\", \"field2\" : 10}]", new TypeToken<List<Pojo>>() {});
assert list.size() == 1;
assert list.get(0).field1.equals("abc");
assert list.get(0).field2 == 10;
output
INFO: Result: [Pojo [field1=abc, field2=10]]
Side notes:
your utility class is named JsonParser
, which collides with class with same name from GSON lib - that can create unnecessary confusion
your method to deserialize json string into object is named convertToString
, but it is doing exact opposite
Generic type argument <T extends Object>
doesn't make much sense, every object instance in java extends Object, so it could be just <T>
Upvotes: 1