跳转至

Java JSON 处理教程

原文: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 从输入源读取JsonObjectJsonArray
JsonWriter JsonObjectJsonArray写入输出源。

JsonValueJsonObjectJsonArrayJsonStringJsonNumber是 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-apijavax.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_OBJECTEND_OBJECTSTART_ARRAYEND_ARRAYKEY_NAMEVALUE_STRINGVALUE_NUMBERVALUE_TRUEVALUE_FALSEVALUE_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 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 数据。

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 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

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



回到顶部