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

发布于 2024-11-02 12:51:59 字数 172 浏览 1 评论 0原文

我正在用 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

夜清冷一曲。 2024-11-09 12:51:59

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

是的,有。如果您不关心反序列化为特定 Java 类型的 JSON 结构只是一个包含键值对的对象,其中所有值都是 JSON 基元,那么该结构可以简单地反序列化为 Map< ;字符串,字符串>。

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

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

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,则输出将变为 {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,这样就不需要如上所述的自定义反序列化处理。

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.

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 plain Object instances for each value -- not String or Integer instances, but just plain Object 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 for JsonPrimitive values. For example, since it's possible to determine whether a JsonPrimitive is a Boolean, with a call to isBoolean(), then one might hope Gson would just construct a Boolean, but it doesn't -- Gson just creates an empty and probably-useless Object.

Here's an example that demonstrates this point.

input.json Contents:

{
  "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);
  }
}

The output of this example is {3=false, one=won, too=22}.

If the Map type in the example is changed to HashMap<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 a String, such that custom deserialization processing as described above wouldn't be necessary.

酸甜透明夹心 2024-11-09 12:51:59

如果你想使用 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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文