将 JSON 反序列化为未知类型的集合
我正在用 Java 编写一个程序,通过调用一些方法向外部 API 发出请求。这些方法中的每一个都会返回不同的 JSON 结构,并且还取决于传递的参数。我的问题是是否有某种方法可以使用 Gson 反序列化响应字符串,而不必为每个方法编写不同的类。
如果不是 Gson,我还可以使用哪个其他库?
谢谢。
I'm writting a program in Java that makes requests to an external API by calling some methods. Each of these methods returns a diferent JSON structure and it also depends on the passed parameters. My question is if there's some way to deserialize the response string using Gson without having to write a different class for each method.
If not Gson, which other library could I use?
Thank you.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
是的,有。如果您不关心反序列化为特定 Java 类型的 JSON 结构只是一个包含键值对的对象,其中所有值都是 JSON 基元,那么该结构可以简单地反序列化为 Map< ;字符串,字符串>。
请注意,
Map
将不起作用,因为它没有为 Gson 反序列化提供足够的类型信息。 Gson 只会为每个值创建普通的Object
实例 - 不是String
或Integer
实例,而只是普通的Object
实例。 JSON 中的实际值不会被反序列化。从表面上看,增强 Gson 来为JsonPrimitive
值创建更多特定于类型的实例似乎是合理的。例如,由于可以通过调用isBoolean()
来确定JsonPrimitive
是否为Boolean
,因此人们可能希望 Gson 能够只是构造一个布尔值,但事实并非如此——Gson 只是创建了一个空的且可能无用的对象。这是一个证明这一点的例子。
input.json 内容:
Foo.java:
此示例的输出为
{3=false, one=won, too=22}
。如果按照另一个答案中的建议将示例中的
Map
类型更改为HashMap
,则输出将变为{3=java.lang. Object@10b61fd1, one=java.lang.Object@24e2dae9, too=java.lang.Object@299209ea}
,这当然可能没用。如果由于某种原因必须反序列化为
HashMap
类型,则需要进行自定义反序列化处理。如果 JSON 结构不是一组简单的键值对,其中值都是 JSON 基元,但包含像 JSON 对象这样的复杂类型的值,即使将所有值转换为
Strings< /code>,那么还需要实现自定义的反序列化处理。
请随时访问 Gson 问题列表并提交改进 JSON 原语反序列化为适当特定的 Java
Object
类型的增强请求,或者拥有一个简单的机制来将 Map 中的任何值(包括复杂的 JSON 类型,如对象和数组)转换为 < code>String,这样就不需要如上所述的自定义反序列化处理。Yes, there is. If the JSON structure that you don't care to deserialize into a specific Java type is just an object that contains key-value pairs, where all of the values are JSON primitives, then the structure can be simply deserialized into a
Map<String, String>
.Note that a
Map<String, Object>
would not work as it does not provide enough type information for Gson to deserialize into. Gson would just create plainObject
instances for each value -- notString
orInteger
instances, but just plainObject
instances. The actual values in the JSON would not be deserialized. On the surface it seems reasonable that Gson could be enhanced to create more type-specific instances forJsonPrimitive
values. For example, since it's possible to determine whether aJsonPrimitive
is aBoolean
, with a call toisBoolean()
, then one might hope Gson would just construct aBoolean
, but it doesn't -- Gson just creates an empty and probably-uselessObject
.Here's an example that demonstrates this point.
input.json Contents:
Foo.java:
The output of this example is
{3=false, one=won, too=22}
.If the
Map
type in the example is changed toHashMap<String, Object>
as recommended in another answer, then the output becomes{3=java.lang.Object@10b61fd1, one=java.lang.Object@24e2dae9, too=java.lang.Object@299209ea}
, which is of course probably useless.If for some reason a type of
HashMap<String, Object>
must be deserialized to, then custom deserialization processing would be necessary.If the JSON structure is not a simple set of key-value pairs, where the values are all JSON primitives, but include values that are complex types like JSON objects, even if it's acceptable to transform all of the values into
Strings
, then it would also be necessary to implement custom deserialization processing.Don't hesitate to head on over to the Gson Issues List and submit an enhancement request for improved JSON primitive deserialization to appropriately specific Java
Object
types, or to have a simple mechanism to transform any value -- including complex JSON types like objects and arrays -- in a Map into aString
, such that custom deserialization processing as described above wouldn't be necessary.如果你想使用 gson,你必须编写不同的类来代表不同方法的响应。如果响应是简单的键值,那么您可以将响应转换为
HashMap
,它将充当“通用”类来满足用例中的所有类型的响应。You have to write different class which would represent the responses from different methods if you want to use gson. If the response is simple key-value, then you can convert the response into a
HashMap<String,Object>
which will act as a 'generic' class to satisfy all type of responses in your use case.