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教程。