Intro to the Jackson ObjectMapper – Jackson ObjectMapper介绍

最后修改: 2016年 7月 18日

中文/混合/英文(键盘快捷键:t)

1. Overview

1.概述

This tutorial focuses on understanding the Jackson ObjectMapper class and how to serialize Java objects into JSON and deserialize JSON string into Java objects.

本教程的重点是了解Jackson ObjectMapper 类,以及如何将Java对象序列化为JSON并将JSON字符串反序列化为Java对象。

To understand more about the Jackson library in general, the Jackson Tutorial is a good place to start.

要了解更多关于Jackson库的总体情况,Jackson教程是一个很好的开始。

2. Dependencies

2.依赖性

Let’s first add the following dependencies to the pom.xml:

让我们首先将以下依赖关系添加到pom.xml

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.13.3</version>
</dependency>

This dependency will also transitively add the following libraries to the classpath:

这个依赖关系也会将以下库添加到classpath中。

  1. jackson-annotations
  2. jackson-core

Always use the latest versions from the Maven central repository for jackson-databind.

始终使用Maven中央仓库的最新版本jackson-databind

3. Reading and Writing Using ObjectMapper

3.使用ObjectMapper读和写

Let’s start with the basic read and write operations.

让我们从基本的读和写操作开始。

The simple readValue API of the ObjectMapper is a good entry point. We can use it to parse or deserialize JSON content into a Java object.

ObjectMapper的简单readValue API是一个很好的切入点。我们可以用它来解析或反序列化JSON内容,使之成为一个Java对象。

Also, on the writing side, we can use the writeValue API to serialize any Java object as JSON output.

此外,在写作方面,我们可以使用writeValue API来将任何Java对象序列化为JSON输出。

We’ll use the following Car class with two fields as the object to serialize or deserialize throughout this article:

在本文中,我们将使用下面这个有两个字段的Car类作为对象来进行序列化或反序列化。

public class Car {

    private String color;
    private String type;

    // standard getters setters
}

3.1. Java Object to JSON

3.1.Java对象到JSON

Let’s see a first example of serializing a Java object into JSON using the writeValue method of the ObjectMapper class:

让我们看看使用ObjectMapper类的writeValue方法将一个Java对象序列化为JSON的第一个例子。

ObjectMapper objectMapper = new ObjectMapper();
Car car = new Car("yellow", "renault");
objectMapper.writeValue(new File("target/car.json"), car);

The output of the above in the file will be:

上述内容在文件中的输出将是。

{"color":"yellow","type":"renault"}

The methods writeValueAsString and writeValueAsBytes of ObjectMapper class generate a JSON from a Java object and return the generated JSON as a string or as a byte array:

writeValueAsStringwriteValueAsBytes类的方法从一个Java对象生成JSON,并将生成的JSON作为字符串或字节数组返回。

String carAsString = objectMapper.writeValueAsString(car);

3.2. JSON to Java Object

3.2. JSON到Java对象

Below is a simple example of converting a JSON String to a Java object using the ObjectMapper class:

下面是一个使用ObjectMapper类将JSON字符串转换为Java对象的简单例子。

String json = "{ \"color\" : \"Black\", \"type\" : \"BMW\" }";
Car car = objectMapper.readValue(json, Car.class);	

The readValue() function also accepts other forms of input, such as a file containing JSON string:

readValue()函数也接受其他形式的输入,例如一个包含JSON字符串的文件。

Car car = objectMapper.readValue(new File("src/test/resources/json_car.json"), Car.class);

or an URL:

或一个URL。

Car car = 
  objectMapper.readValue(new URL("file:src/test/resources/json_car.json"), Car.class);

3.3. JSON to Jackson JsonNode

3.3.JSON到JacksonJsonNode

Alternatively, a JSON can be parsed into a JsonNode object and used to retrieve data from a specific node:

另外,JSON可以被解析成一个JsonNode对象,并用于从一个特定的节点检索数据。

String json = "{ \"color\" : \"Black\", \"type\" : \"FIAT\" }";
JsonNode jsonNode = objectMapper.readTree(json);
String color = jsonNode.get("color").asText();
// Output: color -> Black

3.4. Creating a Java List From a JSON Array String

3.4.从JSON数组字符串创建一个Java列表

We can parse a JSON in the form of an array into a Java object list using a TypeReference:

我们可以使用TypeReference将一个数组形式的JSON解析为一个Java对象列表。

String jsonCarArray = 
  "[{ \"color\" : \"Black\", \"type\" : \"BMW\" }, { \"color\" : \"Red\", \"type\" : \"FIAT\" }]";
List<Car> listCar = objectMapper.readValue(jsonCarArray, new TypeReference<List<Car>>(){});

3.5. Creating Java Map From JSON String

3.5.从JSON字符串创建Java地图

Similarly, we can parse a JSON into a Java Map:

同样地,我们可以将JSON解析为Java Map

String json = "{ \"color\" : \"Black\", \"type\" : \"BMW\" }";
Map<String, Object> map 
  = objectMapper.readValue(json, new TypeReference<Map<String,Object>>(){});

4. Advanced Features

4.高级功能

One of the greatest strengths of the Jackson library is the highly customizable serialization and deserialization process.

Jackson库的最大优势之一是高度可定制的序列化和反序列化过程。

In this section, we’ll go through some advanced features where the input or the output JSON response can be different from the object that generates or consumes the response.

在本节中,我们将讨论一些高级功能,其中输入或输出的JSON响应可以与生成或消费响应的对象不同。

4.1. Configuring Serialization or Deserialization Feature

4.1.配置序列化或反序列化功能

While converting JSON objects to Java classes, in case the JSON string has some new fields, the default process will result in an exception:

在将JSON对象转换为Java类时,如果JSON字符串有一些新的字段,默认过程将导致一个异常。

String jsonString 
  = "{ \"color\" : \"Black\", \"type\" : \"Fiat\", \"year\" : \"1970\" }";

The JSON string in the above example in the default parsing process to the Java object for the Class Car will result in the UnrecognizedPropertyException exception.

上例中的JSON字符串在默认解析过程中对Java对象的Class Car将导致UnrecognizedPropertyException异常。

Through the configure method, we can extend the default process to ignore the new fields:

通过configure方法,我们可以扩展默认流程以忽略新字段

objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
Car car = objectMapper.readValue(jsonString, Car.class);

JsonNode jsonNodeRoot = objectMapper.readTree(jsonString);
JsonNode jsonNodeYear = jsonNodeRoot.get("year");
String year = jsonNodeYear.asText();

Yet another option is based on the FAIL_ON_NULL_FOR_PRIMITIVES, which defines if the null values for primitive values are allowed:

还有一个选项是基于FAIL_ON_NULL_FOR_PRIMITIVES,它定义了是否允许基元值的null值。

objectMapper.configure(DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES, false);

Similarly, FAIL_ON_NUMBERS_FOR_ENUM controls if enum values are allowed to be serialized/deserialized as numbers:

同样,FAIL_ON_NUMBERS_FOR_ENUM控制是否允许将枚举值作为数字进行序列化/反序列化。

objectMapper.configure(DeserializationFeature.FAIL_ON_NUMBERS_FOR_ENUMS, false);

You can find the comprehensive list of serialization and deserialization features on the official site.

你可以在官方网站上找到序列化和反序列化功能的全面清单。

4.2. Creating Custom Serializer or Deserializer

4.2.创建自定义序列化器或反序列化器

Another essential feature of the ObjectMapper class is the ability to register a custom serializer and deserializer.

ObjectMapper类的另一个基本特征是能够注册一个自定义的serializerdeserializer

Custom serializers and deserializers are very useful in situations where the input or the output JSON response is different in structure than the Java class into which it must be serialized or deserialized.

自定义序列化器和反序列化器在输入或输出的JSON响应的结构与必须被序列化或反序列化的Java类不同的情况下非常有用。

Below is an example of a custom JSON serializer:

下面是一个自定义JSON序列化器的例子

public class CustomCarSerializer extends StdSerializer<Car> {
    
    public CustomCarSerializer() {
        this(null);
    }

    public CustomCarSerializer(Class<Car> t) {
        super(t);
    }

    @Override
    public void serialize(
      Car car, JsonGenerator jsonGenerator, SerializerProvider serializer) {
        jsonGenerator.writeStartObject();
        jsonGenerator.writeStringField("car_brand", car.getType());
        jsonGenerator.writeEndObject();
    }
}

This custom serializer can be invoked like this:

这个自定义的序列化器可以像这样被调用。

ObjectMapper mapper = new ObjectMapper();
SimpleModule module = 
  new SimpleModule("CustomCarSerializer", new Version(1, 0, 0, null, null, null));
module.addSerializer(Car.class, new CustomCarSerializer());
mapper.registerModule(module);
Car car = new Car("yellow", "renault");
String carJson = mapper.writeValueAsString(car);

Here’s what the Car looks like (as JSON output) on the client side:

下面是Car在客户端的样子(作为JSON输出)。

var carJson = {"car_brand":"renault"}

And here’s an example of a custom JSON deserializer:

而这里是一个自定义JSON反序列化器的例子。

public class CustomCarDeserializer extends StdDeserializer<Car> {
    
    public CustomCarDeserializer() {
        this(null);
    }

    public CustomCarDeserializer(Class<?> vc) {
        super(vc);
    }

    @Override
    public Car deserialize(JsonParser parser, DeserializationContext deserializer) {
        Car car = new Car();
        ObjectCodec codec = parser.getCodec();
        JsonNode node = codec.readTree(parser);
        
        // try catch block
        JsonNode colorNode = node.get("color");
        String color = colorNode.asText();
        car.setColor(color);
        return car;
    }
}

This custom deserializer can be invoked in this way:

这个自定义的反序列化器可以通过这种方式调用。

String json = "{ \"color\" : \"Black\", \"type\" : \"BMW\" }";
ObjectMapper mapper = new ObjectMapper();
SimpleModule module =
  new SimpleModule("CustomCarDeserializer", new Version(1, 0, 0, null, null, null));
module.addDeserializer(Car.class, new CustomCarDeserializer());
mapper.registerModule(module);
Car car = mapper.readValue(json, Car.class);

4.3. Handling Date Formats

4.3.处理日期格式

The default serialization of java.util.Date produces a number, i.e., epoch timestamp (number of milliseconds since January 1, 1970, UTC). But this is not very human readable and requires further conversion to be displayed in a human-readable format.

java.util.Date的默认序列化会产生一个数字,即纪元时间戳(1970年1月1日以来的毫秒数,UTC)。但这并不是人类可读的,需要进一步转换才能以人类可读的格式显示。

Let’s wrap the Car instance we used so far inside the Request class with the datePurchased property:

让我们用Request类中的Car实例和datePurchased属性来包装我们到目前为止使用的Car实例。

public class Request 
{
    private Car car;
    private Date datePurchased;

    // standard getters setters
}

To control the String format of a date and set it to, e.g., yyyy-MM-dd HH:mm a z, consider the following snippet:

要控制一个日期的字符串格式并将其设置为,例如,yyyy-MM-dd HH:mm a z,请考虑以下代码段。

ObjectMapper objectMapper = new ObjectMapper();
DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm a z");
objectMapper.setDateFormat(df);
String carAsString = objectMapper.writeValueAsString(request);
// output: {"car":{"color":"yellow","type":"renault"},"datePurchased":"2016-07-03 11:43 AM CEST"}

To learn more about serializing dates with Jackson, read our more in-depth write-up.

要了解有关用Jackson序列化日期的更多信息,请阅读我们更深入的文章

4.4. Handling Collections

4.4.处理收藏品

Another small but useful feature available through the DeserializationFeature class is the ability to generate the type of collection we want from a JSON Array response.

通过DeserializationFeature类提供的另一个小但有用的功能是能够从JSON阵列响应中生成我们想要的集合类型。

For example, we can generate the result as an array:

例如,我们可以将结果生成为一个数组。

String jsonCarArray = 
  "[{ \"color\" : \"Black\", \"type\" : \"BMW\" }, { \"color\" : \"Red\", \"type\" : \"FIAT\" }]";
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.configure(DeserializationFeature.USE_JAVA_ARRAY_FOR_JSON_ARRAY, true);
Car[] cars = objectMapper.readValue(jsonCarArray, Car[].class);
// print cars

Or as a List:

或者作为一个列表

String jsonCarArray = 
  "[{ \"color\" : \"Black\", \"type\" : \"BMW\" }, { \"color\" : \"Red\", \"type\" : \"FIAT\" }]";
ObjectMapper objectMapper = new ObjectMapper();
List<Car> listCar = objectMapper.readValue(jsonCarArray, new TypeReference<List<Car>>(){});
// print cars

More information about handling collections with Jackson is available here.

关于用Jackson处理集合的更多信息可在此处获得。

5. Conclusion

5.结论

Jackson is a solid and mature JSON serialization/deserialization library for Java. The ObjectMapper API provides a straightforward way to parse and generate JSON response objects with a lot of flexibility. This article discussed the main features that make the library so popular.

Jackson是一个坚实而成熟的Java的JSON序列化/反序列化库。ObjectMapper API提供了一种直接的方式来解析和生成具有很大灵活性的JSON响应对象。这篇文章讨论了使该库如此受欢迎的主要功能。

The source code that accompanies the article can be found over on GitHub.

伴随文章的源代码可以在GitHub上找到