原文: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 创建我们的应用。

  1. <dependencies>
  2. <dependency>
  3. <groupId>javax.json</groupId>
  4. <artifactId>javax.json-api</artifactId>
  5. <version>1.1</version>
  6. </dependency>
  7. <dependency>
  8. <groupId>org.glassfish</groupId>
  9. <artifactId>javax.json</artifactId>
  10. <version>1.1</version>
  11. </dependency>
  12. </dependencies>

在项目中,我们使用javax.json-api和javax.json依赖项。

JSON-P JsonObjectBuilder示例

在第一个示例中,我们使用对象生成器创建 JSON 字符串。

JsonObjectBuilderEx.java

  1. package com.zetcode;
  2. import javax.json.Json;
  3. import java.time.LocalDate;
  4. public class JsonObjectBuilderEx {
  5. public static void main(String[] args) {
  6. var born = LocalDate.of(1992, 3, 2).toString();
  7. var json = Json.createObjectBuilder()
  8. .add("name", "John Doe")
  9. .add("occupation", "gardener")
  10. .add("born", born).build();
  11. var result = json.toString();
  12. System.out.println(result);
  13. }
  14. }

JSON 字符串被打印到控制台。

  1. var json = Json.createObjectBuilder()
  2. .add("name", "John Doe")
  3. .add("occupation", "gardener")
  4. .add("born", born).build();

用createObjectBuilder()创建一个JsonObjectBuilder。 新的对将插入add()。 最后,使用build()结束字符串。

  1. var result = json.toString();

我们使用toString()将JsonObject转换为字符串。

  1. {"name":"John Doe","occupation":"gardener","born":"1992-03-02"}

这是输出。

PRETTY_PRINTING

通过JsonGenerator.PRETTY_PRINTING配置设置,我们可以设置写入器进行漂亮的打印。

JsonPrettyPrintEx.java

  1. package com.zetcode;
  2. import javax.json.Json;
  3. import javax.json.stream.JsonGenerator;
  4. import java.io.StringWriter;
  5. import java.time.LocalDate;
  6. import java.util.HashMap;
  7. public class JsonPrettyPrintEx {
  8. public static void main(String[] args) {
  9. var born = LocalDate.of(1992, 3, 2).toString();
  10. var json = Json.createObjectBuilder()
  11. .add("name", "John Doe")
  12. .add("occupation", "gardener")
  13. .add("born", born).build();
  14. var config = new HashMap<String, Boolean>();
  15. config.put(JsonGenerator.PRETTY_PRINTING, true);
  16. var jwf = Json.createWriterFactory(config);
  17. var sw = new StringWriter();
  18. try (var jsonWriter = jwf.createWriter(sw)) {
  19. jsonWriter.writeObject(json);
  20. System.out.println(sw.toString());
  21. }
  22. }
  23. }

在示例中,我们创建一个 JSON 对象并将其打印到控制台。 输出打印精美。

  1. var config = new HashMap<String, Boolean>();
  2. config.put(JsonGenerator.PRETTY_PRINTING, true);
  3. var jwf = Json.createWriterFactory(config);

配置文件被传递到JsonWriterFactory。

  1. {
  2. "name": "John Doe",
  3. "occupation": "gardener",
  4. "born": "1992-03-02"
  5. }

这是输出。

JSON-P JsonArrayBuilder

JsonArrayBuilder是用于创建和修改JsonArray对象的构建器。

JsonArrayBuilderEx.java

  1. package com.zetcode;
  2. import javax.json.Json;
  3. import javax.json.stream.JsonGenerator;
  4. import java.io.StringWriter;
  5. import java.time.LocalDate;
  6. import java.util.HashMap;
  7. import java.util.List;
  8. public class JsonArrayBuilderEx {
  9. public static void main(String[] args) {
  10. var ab = Json.createArrayBuilder();
  11. var users = createUsers();
  12. users.forEach(user -> {
  13. var ob = Json.createObjectBuilder();
  14. ob.add("name", user.getName());
  15. ob.add("occupation", user.getOccupation());
  16. ob.add("born", user.getBorn().toString());
  17. ab.add(ob);
  18. });
  19. var config = new HashMap<String, Boolean>();
  20. config.put(JsonGenerator.PRETTY_PRINTING, true);
  21. var jwf = Json.createWriterFactory(config);
  22. var sw = new StringWriter();
  23. try (var jsonWriter = jwf.createWriter(sw)) {
  24. jsonWriter.writeArray(jsonArray);
  25. System.out.println(sw);
  26. }
  27. }
  28. public static List<User> createUsers() {
  29. var born1 = LocalDate.of(1992, 3, 2);
  30. var u1 = new User("John Doe", "gardener", born1);
  31. var born2 = LocalDate.of(1967, 11, 22);
  32. var u2 = new User("Brian Flemming", "teacher", born2);
  33. var born3 = LocalDate.of(1995, 4, 7);
  34. var u3 = new User("Lucy Black", "accountant", born3);
  35. var born4 = LocalDate.of(1972, 8, 30);
  36. var u4 = new User("John Doe", "gardener", born4);
  37. return List.of(u1, u2, u3, u4);
  38. }
  39. }

在该示例中,我们创建了一个用户对象列表,并将其转换为JsonArray。

  1. var ab = Json.createArrayBuilder();

用createArrayBuilder()创建一个JsonArrayBuilder。

  1. users.forEach(user -> {
  2. var ob = Json.createObjectBuilder();
  3. ob.add("name", user.getName());
  4. ob.add("occupation", user.getOccupation());
  5. ob.add("born", user.getBorn().toString());
  6. ab.add(ob);
  7. });

在此for循环中,我们创建 JSON 对象并将其添加到构建器中。

  1. var jsonArray = ab.build();

build()方法从构建器创建JsonArray。

  1. jsonWriter.writeArray(jsonArray);

JsonArray被写入写入器。

  1. [
  2. {
  3. "name": "John Doe",
  4. "occupation": "gardener",
  5. "born": "1992-03-02"
  6. },
  7. {
  8. "name": "Brian Flemming",
  9. "occupation": "teacher",
  10. "born": "1967-11-22"
  11. },
  12. {
  13. "name": "Lucy Black",
  14. "occupation": "accountant",
  15. "born": "1995-04-07"
  16. },
  17. {
  18. "name": "John Doe",
  19. "occupation": "gardener",
  20. "born": "1972-08-30"
  21. }
  22. ]

这是输出。

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

  1. [
  2. {
  3. "name": "John Doe",
  4. "occupation": "gardener",
  5. "born": "1992-03-02"
  6. },
  7. {
  8. "name": "Brian Flemming",
  9. "occupation": "teacher",
  10. "born": "1967-11-22"
  11. },
  12. {
  13. "name": "Lucy Black",
  14. "occupation": "accountant",
  15. "born": "1995-04-07"
  16. },
  17. {
  18. "name": "William Bean",
  19. "occupation": "pilot",
  20. "born": "1977-10-31"
  21. }
  22. ]

我们将解析users.json文件。

JsonParserSimpleEx.java

  1. package com.zetcode;
  2. import javax.json.Json;
  3. import javax.json.stream.JsonParser;
  4. import java.io.FileInputStream;
  5. import java.io.FileNotFoundException;
  6. import java.nio.charset.StandardCharsets;
  7. public class JsonParserSimpleEx {
  8. public static void main(String[] args) throws FileNotFoundException {
  9. var is = new FileInputStream("src/main/resources/users.json");
  10. var factory = Json.createParserFactory(null);
  11. var parser = factory.createParser(is, StandardCharsets.UTF_8);
  12. if (!parser.hasNext() && parser.next() != JsonParser.Event.START_ARRAY) {
  13. return;
  14. }
  15. // looping over object attributes
  16. while (parser.hasNext()) {
  17. var event = parser.next();
  18. // starting object
  19. if (event == JsonParser.Event.START_OBJECT) {
  20. while (parser.hasNext()) {
  21. event = parser.next();
  22. if (event == JsonParser.Event.KEY_NAME) {
  23. var key = parser.getString();
  24. switch (key) {
  25. case "name":
  26. parser.next();
  27. System.out.printf("Name: %s%n", parser.getString());
  28. break;
  29. case "occupation":
  30. parser.next();
  31. System.out.printf("Occupation: %s%n", parser.getString());
  32. break;
  33. case "born":
  34. parser.next();
  35. System.out.printf("Born: %s%n%n", parser.getString());
  36. break;
  37. }
  38. }
  39. }
  40. }
  41. }
  42. }
  43. }

在示例中,我们使用 JSON-P 流式 API 解析users.json文件。

  1. var is = new FileInputStream("src/main/resources/users.json");
  2. var factory = Json.createParserFactory(null);
  3. var parser = factory.createParser(is, StandardCharsets.UTF_8);

从JsonParserFactory创建一个JsonParser。

  1. if (!parser.hasNext() && parser.next() != JsonParser.Event.START_ARRAY) {
  2. return;
  3. }

首先,我们传递数组的开头。

  1. // looping over object attributes
  2. while (parser.hasNext()) {
  3. var event = parser.next();
  4. // starting object
  5. if (event == JsonParser.Event.START_OBJECT) {
  6. ...

然后,我们在while循环中遍历数组。 当我们到达数组末尾时,解析器的hasNext()方法返回false。 我们使用next()拉下一个解析事件。

  1. while (parser.hasNext()) {
  2. event = parser.next();
  3. if (event == JsonParser.Event.KEY_NAME) {
  4. ...

在另一个while循环中,我们遍历当前对象的键。

  1. var key = parser.getString();
  2. switch (key) {
  3. case "name":
  4. parser.next();
  5. System.out.printf("Name: %s%n", parser.getString());
  6. break;
  7. ...

在switch语句中,我们检查键名称,并通过getString()获得其值。

  1. Name: John Doe
  2. Occupation: gardener
  3. Born: 1992-03-02
  4. Name: Brian Flemming
  5. Occupation: teacher
  6. Born: 1967-11-22
  7. Name: Lucy Black
  8. Occupation: accountant
  9. Born: 1995-04-07
  10. Name: William Bean
  11. Occupation: pilot
  12. Born: 1977-10-31

这是输出。

在第二个示例中,我们连接到网站并从路径获取 JSON 数据。

JsonParserEx.java

  1. package com.zetcode;
  2. import javax.json.Json;
  3. import javax.json.stream.JsonParser;
  4. import java.io.IOException;
  5. import java.net.URL;
  6. public class JsonParserEx {
  7. public static void main(String[] args) throws IOException {
  8. var url = new URL("https://jsonplaceholder.typicode.com/posts");
  9. try (var in = url.openStream(); var parser = Json.createParser(in)) {
  10. // starting array
  11. parser.next();
  12. while (parser.hasNext()) {
  13. // starting object
  14. var event1 = parser.next();
  15. if (event1 == JsonParser.Event.START_OBJECT) {
  16. while (parser.hasNext()) {
  17. var event = parser.next();
  18. if (event == JsonParser.Event.KEY_NAME) {
  19. switch (parser.getString()) {
  20. case "userId":
  21. parser.next();
  22. System.out.printf("User Id: %d%n", parser.getInt());
  23. break;
  24. case "id":
  25. parser.next();
  26. System.out.printf("Post Id: %d%n", parser.getInt());
  27. break;
  28. case "title":
  29. parser.next();
  30. System.out.printf("Post title: %s%n", parser.getString());
  31. break;
  32. case "body":
  33. parser.next();
  34. System.out.printf("Post body: %s%n%n", parser.getString());
  35. break;
  36. }
  37. }
  38. }
  39. }
  40. }
  41. }
  42. }
  43. }

该示例处理了 jsonplaceholder.typicode.com 网站上的一百个帖子,该网站是用于测试和原型制作的虚假在线 REST API。

JSON-P JsonGenerator

JsonGenerator以流方式将 JSON 数据写入输出源。 JsonGeneratorFactory包含创建JsonGenerator实例的方法。

JsonGeneratorEx.java

  1. package com.zetcode;
  2. import javax.json.Json;
  3. import javax.json.stream.JsonGenerator;
  4. import java.io.IOException;
  5. import java.nio.charset.StandardCharsets;
  6. import java.nio.file.Files;
  7. import java.nio.file.Paths;
  8. import java.time.LocalDate;
  9. import java.util.HashMap;
  10. import java.util.List;
  11. public class JsonGeneratorEx {
  12. public static void main(String[] args) throws IOException {
  13. var myPath = Paths.get("src/main/resources/users.json");
  14. var config = new HashMap<String, Boolean>();
  15. config.put(JsonGenerator.PRETTY_PRINTING, true);
  16. var factory = Json.createGeneratorFactory(config);
  17. var generator = factory.createGenerator(Files.newBufferedWriter(myPath,
  18. StandardCharsets.UTF_8));
  19. generator.writeStartArray();
  20. var users = generateUsers();
  21. users.forEach(user -> {
  22. generator.writeStartObject();
  23. generator.write("name", user.getName());
  24. generator.write("occupation", user.getOccupation());
  25. generator.write("born", user.getBorn().toString());
  26. generator.writeEnd();
  27. });
  28. generator.writeEnd();
  29. generator.flush();
  30. }
  31. public static List<User> generateUsers() {
  32. var born1 = LocalDate.of(1992, 3, 2);
  33. var u1 = new User("John Doe", "gardener", born1);
  34. var born2 = LocalDate.of(1967, 11, 22);
  35. var u2 = new User("Brian Flemming", "teacher", born2);
  36. var born3 = LocalDate.of(1995, 4, 7);
  37. var u3 = new User("Lucy Black", "accountant", born3);
  38. var born4 = LocalDate.of(1977, 10, 31);
  39. var u4 = new User("William Bean", "pilot", born4);
  40. return List.of(u1, u2, u3, u4);
  41. }
  42. }

该示例从用户列表创建users.json文件。

  1. var myPath = Paths.get("src/main/resources/users.json");
  2. var config = new HashMap<String, Boolean>();
  3. config.put(JsonGenerator.PRETTY_PRINTING, true);
  4. var factory = Json.createGeneratorFactory(config);
  5. var generator = factory.createGenerator(Files.newBufferedWriter(myPath,
  6. StandardCharsets.UTF_8));

用JsonGeneratorFactory创建一个JsonGenerator。 工厂接收配置数据,从而可以进行漂亮的打印。

  1. generator.writeStartArray();

数组从writeStartArray()开始。 稍后以writeEnd()结束。

  1. users.forEach(user -> {
  2. generator.writeStartObject();
  3. generator.write("name", user.getName());
  4. generator.write("occupation", user.getOccupation());
  5. generator.write("born", user.getBorn().toString());
  6. generator.writeEnd();
  7. });

JSON 对象写在forEach循环中。 JSON 对象以writeStartObject()开头,以writeEnd()结束。 键/值对使用write()编写。

  1. generator.flush();

使用flush()将数据从缓冲区刷新到数据源。

在本教程中,我们已经使用 Java JSON-P 读写了 JSON 文件。 您可能也对相关教程感兴趣: Gson 教程, Java DOM 教程, Java SAX 教程和或 Java 教程。