Java JSON 处理
最后修改于 2024 年 1 月 27 日
Java JSON 处理教程展示了如何使用 JSON-P 库来处理 JSON。 这些示例将 Java 对象写入 JSON 文件,并将 JSON 数据读取到 Java 对象中。 代码示例可在作者的 Github 存储库中找到。
JSON-P
Java JSON 处理 API (JSON-P) 提供了可移植的 API,可以使用对象模型和流式 API 来解析、生成、转换和查询 JSON。 JSON-P 中有两种处理 JSON 的方法:流式 API 和对象模型 API。
JSON-P 流式 API
流式 API 将解析和生成控制权交给程序员。 流式 API 提供了一个基于事件的解析器,并允许应用程序开发人员请求下一个事件,而不是在回调中处理该事件。 这被称为拉取方法。
| 名称 | 描述 |
|---|---|
| Json | 包含用于创建 JSON 解析器、生成器及其工厂的静态方法。 |
| JsonParser | 表示从流中读取 JSON 数据的基于事件的解析器。 |
| JsonGenerator | 一次一个值地将 JSON 数据写入流。 |
JSON-P 对象模型 API
对象模型 API 创建一个树状结构,用于表示内存中的 JSON 数据。 可以灵活地导航和查询该树。 另一方面,对象模型 API 通常不如流式模型高效,并且需要更多内存。
| 名称 | 描述 |
|---|---|
| Json | 包含用于创建 JSON 解析器、生成器及其工厂的静态方法。 |
| JsonObjectBuilder | 通过从应用程序代码添加值来在内存中创建对象模型。 |
| JsonArrayBuilder | 通过从应用程序代码添加值来在内存中创建数组模型。 |
| JsonReader | 从输入源读取 JsonObject 或 JsonArray。 |
| JsonWriter | 将 JsonObject 或 JsonArray 写入输出源。 |
JsonValue、JsonObject、JsonArray、JsonString 和 JsonNumber 是 JSON 数据类型。
在我们的示例中,我们使用 JDK 11 和 Maven 来创建我们的应用程序。
<dependencies>
<dependency>
<groupId>javax.json</groupId>
<artifactId>javax.json-api</artifactId>
<version>1.1</version>
</dependency>
<dependency>
<groupId>org.glassfish</groupId>
<artifactId>javax.json</artifactId>
<version>1.1</version>
</dependency>
</dependencies>
在项目中,我们使用 javax.json-api 和 javax.json 依赖项。
JSON-P JsonObjectBuilder 示例
在第一个示例中,我们使用对象构建器来创建 JSON 字符串。
package com.zetcode;
import javax.json.Json;
import java.time.LocalDate;
public class JsonObjectBuilderEx {
public static void main(String[] args) {
var born = LocalDate.of(1992, 3, 2).toString();
var json = Json.createObjectBuilder()
.add("name", "John Doe")
.add("occupation", "gardener")
.add("born", born).build();
var result = json.toString();
System.out.println(result);
}
}
一个 JSON 字符串被打印到控制台。
var json = Json.createObjectBuilder()
.add("name", "John Doe")
.add("occupation", "gardener")
.add("born", born).build();
使用 createObjectBuilder 创建一个 JsonObjectBuilder。 使用 add 插入新对。 最后,使用 build 完成字符串。
var result = json.toString();
我们使用 toString 将 JsonObject 转换为字符串。
{"name":"John Doe","occupation":"gardener","born":"1992-03-02"}
美化打印
使用 JsonGenerator.PRETTY_PRINTING 配置设置,我们可以为美化打印设置写入器。
package com.zetcode;
import javax.json.Json;
import javax.json.stream.JsonGenerator;
import java.io.StringWriter;
import java.time.LocalDate;
import java.util.HashMap;
public class JsonPrettyPrintEx {
public static void main(String[] args) {
var born = LocalDate.of(1992, 3, 2).toString();
var json = Json.createObjectBuilder()
.add("name", "John Doe")
.add("occupation", "gardener")
.add("born", born).build();
var config = new HashMap<String, Boolean>();
config.put(JsonGenerator.PRETTY_PRINTING, true);
var jwf = Json.createWriterFactory(config);
var sw = new StringWriter();
try (var jsonWriter = jwf.createWriter(sw)) {
jsonWriter.writeObject(json);
System.out.println(sw.toString());
}
}
}
在该示例中,我们创建一个 JSON 对象并将其打印到控制台。 输出是经过美化打印的。
var config = new HashMap<String, Boolean>(); config.put(JsonGenerator.PRETTY_PRINTING, true); var jwf = Json.createWriterFactory(config);
配置文件被传递给 JsonWriterFactory。
{
"name": "John Doe",
"occupation": "gardener",
"born": "1992-03-02"
}
JSON-P JsonArrayBuilder
JsonArrayBuilder 是用于创建和修改 JsonArray 对象的构建器。
package com.zetcode;
import javax.json.Json;
import javax.json.stream.JsonGenerator;
import java.io.StringWriter;
import java.time.LocalDate;
import java.util.HashMap;
import java.util.List;
public class JsonArrayBuilderEx {
public static void main(String[] args) {
var ab = Json.createArrayBuilder();
var users = createUsers();
users.forEach(user -> {
var ob = Json.createObjectBuilder();
ob.add("name", user.getName());
ob.add("occupation", user.getOccupation());
ob.add("born", user.getBorn().toString());
ab.add(ob);
});
var config = new HashMap<String, Boolean>();
config.put(JsonGenerator.PRETTY_PRINTING, true);
var jwf = Json.createWriterFactory(config);
var sw = new StringWriter();
try (var jsonWriter = jwf.createWriter(sw)) {
jsonWriter.writeArray(jsonArray);
System.out.println(sw);
}
}
public static List<User> createUsers() {
var born1 = LocalDate.of(1992, 3, 2);
var u1 = new User("John Doe", "gardener", born1);
var born2 = LocalDate.of(1967, 11, 22);
var u2 = new User("Brian Flemming", "teacher", born2);
var born3 = LocalDate.of(1995, 4, 7);
var u3 = new User("Lucy Black", "accountant", born3);
var born4 = LocalDate.of(1972, 8, 30);
var u4 = new User("John Doe", "gardener", born4);
return List.of(u1, u2, u3, u4);
}
}
在该示例中,我们创建一个用户对象列表并将其转换为 JsonArray。
var ab = Json.createArrayBuilder();
使用 createArrayBuilder 创建一个 JsonArrayBuilder。
users.forEach(user -> {
var ob = Json.createObjectBuilder();
ob.add("name", user.getName());
ob.add("occupation", user.getOccupation());
ob.add("born", user.getBorn().toString());
ab.add(ob);
});
在这个 for 循环中,我们创建 JSON 对象并将它们添加到构建器。
var jsonArray = ab.build();
build 方法从构建器创建一个 JsonArray。
jsonWriter.writeArray(jsonArray);
JsonArray 被写入到写入器。
[
{
"name": "John Doe",
"occupation": "gardener",
"born": "1992-03-02"
},
{
"name": "Brian Flemming",
"occupation": "teacher",
"born": "1967-11-22"
},
{
"name": "Lucy Black",
"occupation": "accountant",
"born": "1995-04-07"
},
{
"name": "John Doe",
"occupation": "gardener",
"born": "1972-08-30"
}
]
JSON-P JsonParser
JsonParser 使用拉取解析编程模型解析 JSON。 在此模型中,客户端代码控制线程并调用方法 next 以在处理每个元素后将解析器推进到下一个状态。
解析器生成以下事件之一:START_OBJECT、END_OBJECT、START_ARRAY、END_ARRAY、KEY_NAME、VALUE_STRING、VALUE_NUMBER、VALUE_TRUE、VALUE_FALSE 和 VALUE_NULL。
[
{
"name": "John Doe",
"occupation": "gardener",
"born": "1992-03-02"
},
{
"name": "Brian Flemming",
"occupation": "teacher",
"born": "1967-11-22"
},
{
"name": "Lucy Black",
"occupation": "accountant",
"born": "1995-04-07"
},
{
"name": "William Bean",
"occupation": "pilot",
"born": "1977-10-31"
}
]
我们将解析 users.json 文件。
package com.zetcode;
import javax.json.Json;
import javax.json.stream.JsonParser;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.nio.charset.StandardCharsets;
public class JsonParserSimpleEx {
public static void main(String[] args) throws FileNotFoundException {
var is = new FileInputStream("src/main/resources/users.json");
var factory = Json.createParserFactory(null);
var parser = factory.createParser(is, StandardCharsets.UTF_8);
if (!parser.hasNext() && parser.next() != JsonParser.Event.START_ARRAY) {
return;
}
// looping over object attributes
while (parser.hasNext()) {
var event = parser.next();
// starting object
if (event == JsonParser.Event.START_OBJECT) {
while (parser.hasNext()) {
event = parser.next();
if (event == JsonParser.Event.KEY_NAME) {
var key = parser.getString();
switch (key) {
case "name":
parser.next();
System.out.printf("Name: %s%n", parser.getString());
break;
case "occupation":
parser.next();
System.out.printf("Occupation: %s%n", parser.getString());
break;
case "born":
parser.next();
System.out.printf("Born: %s%n%n", parser.getString());
break;
}
}
}
}
}
}
}
在该示例中,我们使用 JSON-P 流式 API 解析 users.json 文件。
var is = new FileInputStream("src/main/resources/users.json");
var factory = Json.createParserFactory(null);
var parser = factory.createParser(is, StandardCharsets.UTF_8);
从 JsonParserFactory 创建一个 JsonParser。
if (!parser.hasNext() && parser.next() != JsonParser.Event.START_ARRAY) {
return;
}
首先,我们传递数组的开头。
// looping over object attributes
while (parser.hasNext()) {
var event = parser.next();
// starting object
if (event == JsonParser.Event.START_OBJECT) {
...
然后,我们在一个 while 循环中遍历数组。 当我们到达数组的末尾时,解析器的 hasNext 方法返回 false。 我们使用 next 拉取下一个解析事件。
while (parser.hasNext()) {
event = parser.next();
if (event == JsonParser.Event.KEY_NAME) {
...
在另一个 while 循环中,我们遍历当前对象的键。
var key = parser.getString();
switch (key) {
case "name":
parser.next();
System.out.printf("Name: %s%n", parser.getString());
break;
...
在 switch 语句中,我们检查键名并使用 getString 获取其值。
Name: John Doe Occupation: gardener Born: 1992-03-02 Name: Brian Flemming Occupation: teacher Born: 1967-11-22 Name: Lucy Black Occupation: accountant Born: 1995-04-07 Name: William Bean Occupation: pilot Born: 1977-10-31
在第二个示例中,我们连接到一个网站并从一个路径获取 JSON 数据。
package com.zetcode;
import javax.json.Json;
import javax.json.stream.JsonParser;
import java.io.IOException;
import java.net.URL;
public class JsonParserEx {
public static void main(String[] args) throws IOException {
var url = new URL("https://jsonplaceholder.typicode.com/posts");
try (var in = url.openStream(); var parser = Json.createParser(in)) {
// starting array
parser.next();
while (parser.hasNext()) {
// starting object
var event1 = parser.next();
if (event1 == JsonParser.Event.START_OBJECT) {
while (parser.hasNext()) {
var event = parser.next();
if (event == JsonParser.Event.KEY_NAME) {
switch (parser.getString()) {
case "userId":
parser.next();
System.out.printf("User Id: %d%n", parser.getInt());
break;
case "id":
parser.next();
System.out.printf("Post Id: %d%n", parser.getInt());
break;
case "title":
parser.next();
System.out.printf("Post title: %s%n", parser.getString());
break;
case "body":
parser.next();
System.out.printf("Post body: %s%n%n", parser.getString());
break;
}
}
}
}
}
}
}
}
该示例处理来自 jsonplaceholder.typicode.com 网站的一百个帖子,这是一个用于测试和原型设计的虚假在线 REST API。
JSON-P JsonGenerator
JsonGenerator 以流式方式将 JSON 数据写入输出源。 JsonGeneratorFactory 包含用于创建 JsonGenerator 实例的方法。
package com.zetcode;
import javax.json.Json;
import javax.json.stream.JsonGenerator;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.time.LocalDate;
import java.util.HashMap;
import java.util.List;
public class JsonGeneratorEx {
public static void main(String[] args) throws IOException {
var myPath = Paths.get("src/main/resources/users.json");
var config = new HashMap<String, Boolean>();
config.put(JsonGenerator.PRETTY_PRINTING, true);
var factory = Json.createGeneratorFactory(config);
var generator = factory.createGenerator(Files.newBufferedWriter(myPath,
StandardCharsets.UTF_8));
generator.writeStartArray();
var users = generateUsers();
users.forEach(user -> {
generator.writeStartObject();
generator.write("name", user.getName());
generator.write("occupation", user.getOccupation());
generator.write("born", user.getBorn().toString());
generator.writeEnd();
});
generator.writeEnd();
generator.flush();
}
public static List<User> generateUsers() {
var born1 = LocalDate.of(1992, 3, 2);
var u1 = new User("John Doe", "gardener", born1);
var born2 = LocalDate.of(1967, 11, 22);
var u2 = new User("Brian Flemming", "teacher", born2);
var born3 = LocalDate.of(1995, 4, 7);
var u3 = new User("Lucy Black", "accountant", born3);
var born4 = LocalDate.of(1977, 10, 31);
var u4 = new User("William Bean", "pilot", born4);
return List.of(u1, u2, u3, u4);
}
}
该示例从用户列表创建一个 users.json 文件。
var myPath = Paths.get("src/main/resources/users.json");
var config = new HashMap<String, Boolean>();
config.put(JsonGenerator.PRETTY_PRINTING, true);
var factory = Json.createGeneratorFactory(config);
var generator = factory.createGenerator(Files.newBufferedWriter(myPath,
StandardCharsets.UTF_8));
使用 JsonGeneratorFactory 创建一个 JsonGenerator。 工厂接收配置数据,该数据启用美化打印。
generator.writeStartArray();
使用 writeStartArray 启动一个数组。 它稍后使用 writeEnd 结束。
users.forEach(user -> {
generator.writeStartObject();
generator.write("name", user.getName());
generator.write("occupation", user.getOccupation());
generator.write("born", user.getBorn().toString());
generator.writeEnd();
});
JSON 对象在 forEach 循环中写入。 使用 writeStartObject 启动一个 JSON 对象,并使用 writeEnd 结束。 使用 write 写入键/值对。
generator.flush();
数据使用 flush 从缓冲区刷新到数据源。
来源
在本文中,我们已经使用 Java JSON-P 读取和写入了 JSON 文件。
作者
列出所有Java教程。