JSON Processing in Java EE 7 – Java EE 7中的JSON处理

最后修改: 2017年 1月 22日


1. Overview


This article will show you how to process JSON using only core Java EE, without the use of third-party dependencies like Jersey or Jackson. Pretty much everything we’ll be using is provided by the javax.json package.

本文将向您展示如何仅使用核心Java EE来处理JSON,而不使用Jersey或Jackson等第三方依赖项。我们将使用的几乎所有东西都由javax.json包提供。

2. Writing an Object to JSON String


Converting a Java object into a JSON String is super easy. Let’s assume we have a simple Person class:

将一个Java对象转换为JSON String是非常容易的。让我们假设我们有一个简单的Person类。

public class Person {
    private String firstName;
    private String lastName;
    private Date birthdate;

    // getters and setters

To convert an instance of that class to a JSON String, first we need to create an instance of JsonObjectBuilder and add property/value pairs using the add() method:

要将该类的一个实例转换为JSON String,首先我们需要创建一个JsonObjectBuilder的实例,并使用add()方法添加属性/值对。

JsonObjectBuilder objectBuilder = Json.createObjectBuilder()
  .add("firstName", person.getFirstName())
  .add("lastName", person.getLastName())
  .add("birthdate", new SimpleDateFormat("DD/MM/YYYY")

Notice that the add() method has a few overloaded versions. It can receive most of the primitive types (as well as boxed objects) as its second parameter.


Once we’re done setting the properties we just need to write the object into a String:


JsonObject jsonObject = objectBuilder.build();
String jsonString;
try(Writer writer = new StringWriter()) {
    jsonString = writer.toString();

And that’s it! The generated String will look like this:



2.1. Using JsonArrayBuilder to Build Arrays


Now, to add a little more complexity to our example, let’s assume that the Person class was modified to add a new property called emails which will contain a list of email addresses:

现在,为了给我们的例子增加一点复杂性,让我们假设Person 类被修改以添加一个名为emails 的新属性,它将包含一个电子邮件地址的列表。

public class Person {
    private String firstName;
    private String lastName;
    private Date birthdate;
    private List<String> emails;
    // getters and setters


To add all the values from that list to the JsonObjectBuilder we’ll need the help of JsonArrayBuilder:


JsonArrayBuilder arrayBuilder = Json.createArrayBuilder();
for(String email : person.getEmails()) {
objectBuilder.add("emails", arrayBuilder);

Notice that we’re using yet another overloaded version of the add() method that takes a JsonArrayBuilder object as its second parameter.


So, let’s look at the generated String for a Person object with two email addresses:



2.2. Formatting the Output With PRETTY_PRINTING


So we have successfully converted a Java object to a valid JSON String. Now, before moving to the next section, let’s add some simple formatting to make the output more “JSON-like” and easier to read.

所以我们已经成功地将一个Java对象转换为一个有效的JSON String。现在,在进入下一节之前,让我们添加一些简单的格式化,使输出更 “像JSON”,更容易阅读。

In the previous examples, we created a JsonWriter using the straightforward Json.createWriter() static method. In order to get more control of the generated String, we will leverage Java 7’s JsonWriterFactory ability to create a writer with a specific configuration.

在前面的例子中,我们使用直接的Json.createWriter()静态方法创建了一个JsonWriter。为了对生成的String进行更多的控制,我们将利用Java 7的JsonWriterFactory能力来创建一个具有特定配置的写入器。

Map<String, Boolean> config = new HashMap<>();

config.put(JsonGenerator.PRETTY_PRINTING, true);
JsonWriterFactory writerFactory = Json.createWriterFactory(config);
String jsonString;
try(Writer writer = new StringWriter()) {
    jsonString = writer.toString();

The code may look a bit verbose, but it really doesn’t do much.


First, it creates an instance of JsonWriterFactory passing a configuration map to its constructor. The map contains only one entry which sets true to the PRETTY_PRINTING property. Then, we use that factory instance to create a writer, instead of using Json.createWriter().

首先,它创建了一个JsonWriterFactory的实例,向其构造函数传递一个配置图。该地图只包含一个条目,即对PRETTY_PRINTING属性设置为 “true”。然后,我们使用该工厂实例来创建一个写作者,而不是使用Json.createWriter()

The new output will contain the distinctive line breaks and tabulation that characterizes a JSON String:

新的输出将包含独特的换行符和制表符,这是JSON String的特点。


3. Building a Java Object From a String


Now let’s do the opposite operation: convert a JSON String into a Java object.

现在让我们做一个相反的操作:将JSON String转换成一个Java对象。

The main part of the conversion process revolves around JsonObject. To create an instance of this class, use the static method Json.createReader() followed by readObject():


JsonReader reader = Json.createReader(new StringReader(jsonString));

JsonObject jsonObject = reader.readObject();

The createReader() method takes an InputStream as a parameter. In this example, we’re using a StringReader, since our JSON is contained in a String object, but this same method could be used to read content from a file, for example, using FileInputStream.


With an instance of JsonObject at hand, we can read the properties using the getString() method and assign the obtained values to a newly created instance of our Person class:

有了JsonObject的实例,我们可以使用getString() 方法读取属性,并将获得的值分配给新创建的Person 类实例。

Person person = new Person();


3.1. Using JsonArray to Get List Values


We’ll need to use a special class, called JsonArray to extract list values from JsonObject:


JsonArray emailsJson = jsonObject.getJsonArray("emails");

List<String> emails = new ArrayList<>();

for (JsonString j : emailsJson.getValuesAs(JsonString.class)) {


That’s it! We have created a complete instance of Person from a Json String.

这就是了!我们已经从一个Json String中创建了一个完整的Person的实例。

4. Querying for Values


Now, let’s assume we are interested in a very specific piece of data that lies inside a JSON String.

现在,让我们假设我们对位于JSON String内的一个非常具体的数据感兴趣。

Consider the JSON below representing a client from a pet shop. Let’s say that, for some reason, you need to get the name of the third pet from the pets list:


    "ownerName": "Robert",
    "pets": [{
        "name": "Kitty",
        "type": "cat"
    }, {
        "name": "Rex",
        "type": "dog"
    }, {
        "name": "Jake",
        "type": "dog"

Converting the whole text into a Java object just to get a single value wouldn’t be very efficient. So, let’s check a couple of strategies to query JSON Strings without having to go through the whole conversion ordeal.

如果只是为了得到一个单一的值而将整个文本转换成一个Java对象,效率就不高了。因此,让我们看看有哪些策略可以查询JSON Strings,而不必经历整个转换过程。

4.1. Querying Using Object Model API


Querying for a property’s value with a known location in the JSON structure is straightforward. We can use an instance of JsonObject, the same class used in previous examples:


JsonReader reader = Json.createReader(new StringReader(jsonString));

JsonObject jsonObject = reader.readObject();

String searchResult = jsonObject

The catch here is to navigate through jsonObject properties using the correct sequence of get*() methods.


In this example, we first get a reference to the “pets” list using getJsonArray(), which returns a list with 3 records. Then, we use getJsonObject() method, which takes an index as a parameter, returning another JsonObject representing the third item in the list. Finally, we use getString() to get the string value we are looking for.

在这个例子中,我们首先使用getJsonArray()获得对 “pets “列表的引用,它返回一个有3条记录的列表。然后,我们使用getJsonObject()方法,它以一个索引为参数,返回另一个JsonObject,代表列表中的第三个项目。最后,我们使用getString()来获取我们正在寻找的字符串值。

4.2. Querying Using Streaming API


Another way to perform precise queries on a JSON String is using the Streaming API, which has JsonParser as its main class.

另一种对JSON String进行精确查询的方法是使用Streaming API,它将JsonParser作为其主类。

JsonParser provides extremely fast, read-only, forward access to JS, with the drawback of being somewhat more complicated than the Object Model:


JsonParser jsonParser = Json.createParser(new StringReader(jsonString));

int count = 0;
String result = null;

while(jsonParser.hasNext()) {
    Event e = jsonParser.next();
    if (e == Event.KEY_NAME) {
        if(jsonParser.getString().equals("name")) {
            if(++count == 3) {
                result = jsonParser.getString();

This example delivers the same result as the previous one. It returns the name from the third pet in the pets list.


Once a JsonParser is created using Json.createParser(), we need to use an iterator (hence the “forward access” nature of the JsonParser) to navigate through the JSON tokens until we get to the property (or properties) we are looking for.

一旦使用JsonParser创建了Json.createParser(),我们需要使用一个迭代器(因此JsonParser的 “向前访问 “性质)来浏览JSON令牌,直到我们到达我们正在寻找的属性(或属性)。

Every time we step through the iterator we move to the next token of the JSON data. So we have to be careful to check if the current token has the expected type. This is done by checking the Event returned by the next() call.

每当我们通过迭代器时,我们就会移动到JSON数据的下一个标记。所以我们必须小心地检查当前标记是否具有预期的类型。这是通过检查Event返回的next() 调用来完成的。

There are many different types of tokens. In this example, we are interested in the KEY_NAME types, which represent the name of a property (e.g. “ownerName”, “pets”, “name”, “type”). Once we stepped through a KEY_NAME token with a value of “name” for the third time, we know that the next token will contain a string value representing the name of the third pet from the list.

有许多不同类型的令牌。在这个例子中,我们对KEY_NAME类型感兴趣,它代表一个属性的名称(例如 “ownerName”、”pets”、”name”、”type”)。一旦我们第三次踏过一个值为 “name “的KEY_NAME标记,我们知道下一个标记将包含一个字符串值,代表列表中第三个宠物的名字。

This is definitely harder than using the Object Model API, especially for more complicated JSON structures. The choice between one or the other, as always, depends on the specific scenario you will be dealing with.


5. Conclusion


We have covered a lot of ground on the Java EE JSON Processing API with a couple of simple examples. To learn other cool stuff about JSON processing, check our series of Jackson articles.

我们已经通过几个简单的例子介绍了Java EE JSON处理API的很多内容。要了解有关JSON处理的其他很酷的东西,请查看我们的杰克逊系列文章

Check the source code of the classes used in this article, as well as some unit tests, in our GitHub repository.