【发布时间】:2011-04-18 01:13:06
【问题描述】:
我正在用 Java 编写一个程序,通过调用一些方法向外部 API 发出请求。这些方法中的每一个都返回不同的 JSON 结构,它还取决于传递的参数。我的问题是,是否有某种方法可以使用 Gson 反序列化响应字符串,而不必为每种方法编写不同的类。
如果不是 Gson,我可以使用其他哪个库?
谢谢。
【问题讨论】:
我正在用 Java 编写一个程序,通过调用一些方法向外部 API 发出请求。这些方法中的每一个都返回不同的 JSON 结构,它还取决于传递的参数。我的问题是,是否有某种方法可以使用 Gson 反序列化响应字符串,而不必为每种方法编写不同的类。
如果不是 Gson,我可以使用其他哪个库?
谢谢。
【问题讨论】:
我的问题是,是否有某种方法可以使用 Gson 反序列化响应字符串,而不必为每种方法编写不同的类。
是的,有。如果您不想反序列化为特定 Java 类型的 JSON 结构只是一个包含键值对的对象,其中所有值都是 JSON 基元,那么该结构可以简单地反序列化为 Map<String, String>。
请注意,Map<String, Object> 不起作用,因为它没有为 Gson 提供足够的类型信息来反序列化。 Gson 只会为每个值创建普通的 Object 实例——不是 String 或 Integer 实例,而只是普通的 Object 实例。 JSON 中的实际值不会被反序列化。从表面上看,可以增强 Gson 以为JsonPrimitive 值创建更多特定于类型的实例似乎是合理的。例如,既然可以通过调用isBoolean() 来确定@987654332@ 是否是Boolean,那么人们可能希望Gson 只构造一个Boolean,但它没有——Gson 只是创建一个空的而且可能没用的Object。
这里有一个例子来说明这一点。
input.json 内容:
{
"one":"won",
"too":22,
"3":false
}
Foo.java:
import java.io.FileReader;
import java.lang.reflect.Type;
import java.util.Map;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
public class Foo
{
public static void main(String[] args) throws Exception
{
Gson gson = new Gson();
Type mapOfStringObjectType = new TypeToken<Map<String, String>>() {}.getType();
Map<String, String> map = gson.fromJson(new FileReader("input.json"), mapOfStringObjectType);
System.out.println(map);
}
}
这个例子的输出是{3=false, one=won, too=22}。
如果示例中的Map类型按照另一个答案的建议改为HashMap<String, Object>,那么输出就变成{3=java.lang.Object@10b61fd1, one=java.lang.Object@24e2dae9, too=java.lang.Object@299209ea},这当然可能没用了。
如果出于某种原因必须将HashMap<String, Object> 类型反序列化为,则需要自定义反序列化处理。
如果 JSON 结构不是一组简单的键值对,其中的值都是 JSON 基元,但包含复杂类型的值,例如 JSON 对象,即使将所有值转换为 @987654344 也是可以接受的@,那么还需要实现自定义的反序列化处理。
不要犹豫,前往 the Gson Issues List 并提交改进请求以改进 JSON 原语反序列化到适当特定的 Java Object 类型,或者拥有一个简单的机制来转换任何值 - 包括复杂的 JSON 类型比如对象和数组——在一个映射到String中,这样就不需要如上所述的自定义反序列化处理。
【讨论】:
如果你想使用 gson,你必须编写不同的类来代表不同方法的响应。如果响应是简单的键值对,那么您可以将响应转换为 HashMap<String,Object>,它将充当“通用”类以满足您用例中所有类型的响应。
【讨论】: