🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
# Java JSON 处理教程 原文:http://zetcode.com/java/jsonp/ Java JSON 处理教程展示了如何使用 JSON-P 库来处理 JSON。 这些示例将 Java 对象写入 JSON 文件,并将 JSON 数据读取到 Java 对象。 在作者的 Github [仓库](https://github.com/janbodnar/Java-Advanced/tree/master/json/jsonp)中提供了代码示例。 ## 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 创建我们的应用。 ```java <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` ```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 字符串被打印到控制台。 ```java var json = Json.createObjectBuilder() .add("name", "John Doe") .add("occupation", "gardener") .add("born", born).build(); ``` 用`createObjectBuilder()`创建一个`JsonObjectBuilder`。 新的对将插入`add()`。 最后,使用`build()`结束字符串。 ```java var result = json.toString(); ``` 我们使用`toString()`将`JsonObject`转换为字符串。 ```java {"name":"John Doe","occupation":"gardener","born":"1992-03-02"} ``` 这是输出。 ## `PRETTY_PRINTING` 通过`JsonGenerator.PRETTY_PRINTING`配置设置,我们可以设置写入器进行漂亮的打印。 `JsonPrettyPrintEx.java` ```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 对象并将其打印到控制台。 输出打印精美。 ```java var config = new HashMap<String, Boolean>(); config.put(JsonGenerator.PRETTY_PRINTING, true); var jwf = Json.createWriterFactory(config); ``` 配置文件被传递到`JsonWriterFactory`。 ```java { "name": "John Doe", "occupation": "gardener", "born": "1992-03-02" } ``` 这是输出。 ## JSON-P `JsonArrayBuilder` `JsonArrayBuilder`是用于创建和修改`JsonArray`对象的构建器。 `JsonArrayBuilderEx.java` ```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`。 ```java var ab = Json.createArrayBuilder(); ``` 用`createArrayBuilder()`创建一个`JsonArrayBuilder`。 ```java 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 对象并将其添加到构建器中。 ```java var jsonArray = ab.build(); ``` `build()`方法从构建器创建`JsonArray`。 ```java jsonWriter.writeArray(jsonArray); ``` `JsonArray`被写入写入器。 ```java [ { "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` ```java [ { "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` ```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 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`文件。 ```java var is = new FileInputStream("src/main/resources/users.json"); var factory = Json.createParserFactory(null); var parser = factory.createParser(is, StandardCharsets.UTF_8); ``` 从`JsonParserFactory`创建一个`JsonParser`。 ```java if (!parser.hasNext() && parser.next() != JsonParser.Event.START_ARRAY) { return; } ``` 首先,我们传递数组的开头。 ```java // looping over object attributes while (parser.hasNext()) { var event = parser.next(); // starting object if (event == JsonParser.Event.START_OBJECT) { ... ``` 然后,我们在`while`循环中遍历数组。 当我们到达数组末尾时,解析器的`hasNext()`方法返回`false`。 我们使用`next()`拉下一个解析事件。 ```java while (parser.hasNext()) { event = parser.next(); if (event == JsonParser.Event.KEY_NAME) { ... ``` 在另一个`while`循环中,我们遍历当前对象的键。 ```java var key = parser.getString(); switch (key) { case "name": parser.next(); System.out.printf("Name: %s%n", parser.getString()); break; ... ``` 在`switch`语句中,我们检查键名称,并通过`getString()`获得其值。 ```java 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 数据。 `JsonParserEx.java` ```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 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`实例的方法。 `JsonGeneratorEx.java` ```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`文件。 ```java 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`。 工厂接收配置数据,从而可以进行漂亮的打印。 ```java generator.writeStartArray(); ``` 数组从`writeStartArray()`开始。 稍后以`writeEnd()`结束。 ```java 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()`编写。 ```java generator.flush(); ``` 使用`flush()`将数据从缓冲区刷新到数据源。 在本教程中,我们已经使用 Java JSON-P 读写了 JSON 文件。 您可能也对相关教程感兴趣: [Gson 教程](/java/gson/), [Java DOM 教程](/java/dom/), [Java SAX 教程](/java/sax/)和或 [Java 教程](/lang/java/)。