概述

在这个快速教程中,我们将创建能够从任何URL读取JSON数据的方法。我们将从核心Java类开始,然后使用一些库来简化我们的代码。

2. 使用核心Java类

在Java中,从URL读取数据的一种最简单方法是使用URL类。 使用它时,我们打开到URL的输入流,创建一个输入流阅读器,然后读取所有字符。我们将这些字符追加到StringBuilder中,然后以String的形式返回:

public static String stream(URL url) {
    try (InputStream input = url.openStream()) {
        InputStreamReader isr = new InputStreamReader(input);
        BufferedReader reader = new BufferedReader(isr);
        StringBuilder json = new StringBuilder();
        int c;
        while ((c = reader.read()) != -1) {
            json.append((char) c);
        }
        return json.toString();
    }
}

然而,这样的代码包含了很多重复的样板代码。如果我们想将JSON数据转换为地图或Java对象,还需要更多的代码。即使使用Java 11的新HttpClient,对于简单的GET请求,代码量仍然很大。而且,它也无法帮助我们将响应从字符串转换为POJO。因此,让我们探索更简单的方法来实现这一点。

3. 使用commons-io和org.json

一个非常受欢迎的库是Apache Commons IO我们将使用IOUtils从URL读取并获取一个String。然后,我们将使用JSON-Java (org.json)库将其转换为JSONObject这是json.org为Java提供的参考实现。现在,让我们在一个新方法中结合它们:

public static JSONObject getJson(URL url) {
    String json = IOUtils.toString(url, Charset.forName("UTF-8"));
    return new JSONObject(json);
}

有了JSONObject,我们可以对任何属性调用get()方法并得到一个Object。对于特定类型,也有相应命名的方法。例如:

jsonObject.getString("stringProperty");

4. 使用Jackson和ObjectMapper减少代码量

有许多解决方案可以将JSON转换为POJO并反向操作。但Jackson在像Jersey等项目中被广泛使用,以及其他JAX-RS实现。让我们在pom.xml中添加所需的依赖:

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.13.3</version>
</dependency>

有了这个,我们不仅可以轻松地从URL读取JSON,还可以同时将其转换为POJO。

4.1. 将JSON反序列化为泛型对象

Jackson的主要功能来自ObjectMapper。对于ObjectMapper,最常见的场景是给它一个String输入,然后获取一个对象。幸运的是,ObjectMapper也可以直接从互联网URL读取输入:

public static JsonNode get(URL url) {
    ObjectMapper mapper = new ObjectMapper();
    return mapper.readTree(url);
}

通过readTree(),我们得到了一个JsonNode,这是一个树形结构。我们使用get()方法来读取属性:

json.get("propertyName");

因此,如果我们不想映射响应到特定类,就不需要这样做。

4.2. 将JSON反序列化为自定义类

但对于更复杂的对象,创建一个表示我们期望的JSON结构的类很有帮助。我们可以使用泛型创建一个方法版本,以便使用readValue()将响应映射到我们想要的任何类。

public static <T> T get(URL url, Class<T> type) {
    ObjectMapper mapper = new ObjectMapper();
    return mapper.readValue(url, type);
}

只要我们的对象的属性和结构匹配,我们就能得到一个新的实例,其中填充了来自JSON响应的值。

5. 总结

在这篇文章中,我们学习了如何向URL发送请求并获取一个JSON字符串。然后,我们使用了一些库来简化代码。最后,我们在几行代码中就完成了从JSON响应到POJO的读取和映射。

一如既往,源代码可在GitHub上找到。