英文:
How to handle Generic types with gson?
问题
以下是翻译好的内容:
我创建了一个类来封装Gson的序列化和反序列化行为。思路是使这个类完全通用,以便软件中的任何部分都可以使用它。
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;
}
}
我在反序列化的过程中遇到了问题(方法convertToString)。这行代码:T result = gson.fromJson(jsonString, type); 在编译时抛出以下错误:
“无法确定
我理解这意味着代码在某种程度上过于模糊和不安全。在这个版本之前,我传递的是名为object的参数,而不是变量type,但问题是返回的对象存在问题,在代码执行后会抛出NullPointerException。我阅读了关于Gson和泛型类型的问题,所以我进入了实际版本。
以防万一,这是对有问题方法的调用(response是一个字符串):
JsonParser.convertToString(response, Response.class);
所以问题是:如何使这个代码能够编译,并保持我的方法在意图上是通用的?
英文:
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>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?
答案1
得分: 1
不要在实用方法中创建类型标记:
Type type = new TypeToken<T>() {}.getType();
让调用者为您创建它:
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;
}
示例:
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;
输出:
INFO: Result: [Pojo [field1=abc, field2=10]]
附注:
-
您的实用类命名为
JsonParser
,这与同名的类GSON库中的类冲突,可能会引起不必要的混淆。 -
将JSON字符串反序列化为对象的方法命名为
convertToString
,但实际上它执行的是相反的操作。 -
泛型类型参数
<T extends Object>
没有太多意义,Java中的每个对象实例都扩展自Object,因此可以简单地写成<T>
。
英文:
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>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论