将JSON反序列化为未知类型的集合

时间:2011-04-18 01:13:06

标签: java json gson

我正在用Java编写一个程序,通过调用某些方法向外部API发出请求。这些方法中的每一个都返回不同的JSON结构,它还取决于传递的参数。我的问题是,是否有某种方法可以使用Gson反序列化响应字符串,而无需为每个方法编写不同的类。

如果不是Gson,我可以使用哪个其他库?

谢谢。

2 个答案:

答案 0 :(得分:4)

  

我的问题是,是否有某种方法可以使用Gson反序列化响应字符串,而无需为每个方法编写不同的类。

是的,有。如果您不关心反序列化为特定Java类型的JSON结构只是一个包含键值对的对象,其中所有值都是JSON基元,那么可以将结构简单地反序列化为{{1} }。

请注意,Map<String, String>不起作用,因为它没有为Gson提供足够的类型信息来反序列化。 Gson只为每个值创建普通的Map<String, Object>个实例 - 不是ObjectString个实例,而只是普通的Integer个实例。 JSON中的实际值不会反序列化。从表面上看,可以增强Gson以为Object值创建更多特定于类型的实例,这似乎是合理的。例如,由于可以通过调用JsonPrimitive来确定JsonPrimitive是否为Boolean,因此可能希望Gson只构建isBoolean(),但它不会--Gson只会创建一个空的且可能无用的Boolean

这是一个证明这一点的例子。

input.json内容:

Object

<强> Foo.java:

{
  "one":"won",
  "too":22,
  "3":false
}

此示例的输出为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} 的类型反序列化,则需要进行自定义反序列化处理。

如果JSON结构不是一组简单的键值对,其中值都是JSON基元,但包含像JSON对象这样的复杂类型的值,即使可以将所有值转换为{{ 1}},然后还需要实现自定义反序列化处理。

不要犹豫,转到the Gson Issues List并向适当特定的Java HashMap<String, Object>类型提交改进的JSON原语反序列化的增强请求,或者提供一个简单的机制来转换任何值 - 包括复杂的JSON类型,如对象和数组 - 在Map中导入Strings,这样就不需要上面描述的自定义反序列化处理。

答案 1 :(得分:1)

如果你想使用gson,你必须编写不同的类来表示来自不同方法的响应。如果响应是简单的键值,那么您可以将响应转换为HashMap<String,Object>,它将充当“通用”类,以满足您的用例中的所有类型的响应。