原文:http://zetcode.com/java/jsonp/
Java JSON 处理教程展示了如何使用 JSON-P 库来处理 JSON。 这些示例将 Java 对象写入 JSON 文件,并将 JSON 数据读取到 Java 对象。 在作者的 Github 仓库中提供了代码示例。
JSON-P
用于 JSON 处理的 Java 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 字符串。
JsonObjectBuilderEx.java
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"}
这是输出。
PRETTY_PRINTING
通过JsonGenerator.PRETTY_PRINTING配置设置,我们可以设置写入器进行漂亮的打印。
JsonPrettyPrintEx.java
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对象的构建器。
JsonArrayBuilderEx.java
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。
users.json
[{"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文件。
JsonParserSimpleEx.java
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 attributeswhile (parser.hasNext()) {var event = parser.next();// starting objectif (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 attributeswhile (parser.hasNext()) {var event = parser.next();// starting objectif (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 DoeOccupation: gardenerBorn: 1992-03-02Name: Brian FlemmingOccupation: teacherBorn: 1967-11-22Name: Lucy BlackOccupation: accountantBorn: 1995-04-07Name: William BeanOccupation: pilotBorn: 1977-10-31
这是输出。
在第二个示例中,我们连接到网站并从路径获取 JSON 数据。
JsonParserEx.java
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 arrayparser.next();while (parser.hasNext()) {// starting objectvar 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实例的方法。
JsonGeneratorEx.java
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循环中。 JSON 对象以writeStartObject()开头,以writeEnd()结束。 键/值对使用write()编写。
generator.flush();
使用flush()将数据从缓冲区刷新到数据源。
在本教程中,我们已经使用 Java JSON-P 读写了 JSON 文件。 您可能也对相关教程感兴趣: Gson 教程, Java DOM 教程, Java SAX 教程和或 Java 教程。
