If you think the content of this blog is helpful or inspiring to you, please follow my blog to get the latest technical articles and tutorials as soon as possible. At the same time, you are also welcome to leave a message in the comment area to share your thoughts and suggestions. Thank you for your support!
1. Preamble
In modern web development, JSON (JavaScript Object Notation) has become a widely used data format for front-end and back-end data transmission and storage. Java is an object-oriented programming language, and JSON is data in a key-value pair format, so in Java, you need to convert a Java object to a JSON string, or convert a JSON string to a Java object. This process is the serialization and deserialization of JSON.
For JSON serialization and deserialization in Java, there are many open source libraries to choose from, of which the Jackson library is one of the most popular. The Jackson library provides a wealth of features for flexible JSON serialization and deserialization with excellent performance.
This article will introduce the JSON serialization and deserialization of the Jackson library, including the serialization and deserialization of basic objects, collections, custom types, enumeration types, and Java time types. This article aims to let readers quickly understand and use the Jackson library for JSON serialization and deserialization.
2. What is JSON serialization and deserialization
JSON serialization is the process of converting a Java object into a JSON string. During the JSON serialization process, the properties of the Java object will be converted into key-value pairs of the JSON object. If the Java object contains other Java objects or collections, these nested objects will also be converted into nested JSON objects and JSON arrays.
JSON deserialization is the process of converting a JSON string into a Java object. During the JSON deserialization process, the key-value pairs of the JSON object will be converted to the properties of the Java object. If the JSON object contains other JSON objects or JSON arrays, these nested JSONs will also be converted to nested Java objects and Java collections.
Three, Jackson library introduction
The Jackson library is a Java-based JSON processing library, which provides a flexible JSON parser and JSON generator, which can easily convert Java objects and JSON data. The Jackson library is very simple to use and has excellent performance, so it is widely used in Java development.
The Jackson library has two core classes: ObjectMapper
and JsonNode
.
The classObjectMapper
is the most important class in the Jackson library, which provides the conversion between serialization and deserialization of Java objects and JSON. ObjectMapper
Instances of the class
The classJsonNode
is an abstract class that represents a JSON node. The classJsonNode
has multiple subclasses, such as ObjectNode
, ArrayNode
,, ValueNode
etc. , corresponding to objects, arrays, and values in JSON. The classJsonNode
provides convenience methods to read the value of a JSON node.
4. Basic type JSON serialization
1. Object serialization
The most basic way to convert a Java object to a JSON string is to
ObjectMapper
usewriteValueAsString
the method of the class. This method receives a Java object as a parameter and returns a JSON string.
For example:
ObjectMapper mapper = new ObjectMapper();
User user = new User("Tom", 20);
String json = mapper.writeValueAsString(user);
In the above code, we create an User
object and use ObjectMapper
the class to serialize it into a JSON string. User
The definition of the class
public class User {
private String name;
private int age;
public User() {
}
public User(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
The resulting JSON string is as follows:
{"name":"Tom","age":20}
2. Collection serialization
In addition to serializing a single Java object, the Jackson library also supports serializing Java collections, including
List
,Set
andMap
etc. A Java collection can be serialized into a JSON string using the method ofObjectMapper
the class .writeValueAsString
ObjectMapper mapper = new ObjectMapper();
List<User> users = new ArrayList<>();
users.add(new User("Tom", 20));
users.add(new User("Jerry", 22));
String json = mapper.writeValueAsString(users);
In the above code, we create a List
collection and User
add two objects to the collection, and then use ObjectMapper
the class to serialize the collection into a JSON string.
The resulting JSON string is as follows:
[{"name":"Tom","age":20},{"name":"Jerry","age":22}]
3. Serialized enumeration type
In Java, an enumeration type is a common data type, which is usually used to represent a limited set of values. Serializing an enum type to a JSON string using the Jackson library is also a common operation. Here is the definition of a simple enumerated type:
public enum Gender {
MALE, FEMALE
}
To serialize an enumeration type into a JSON string, we just need to add @JsonFormat
the annotation and specify the serialization format. For example, the following code will serialize an enum type using uppercase letters:
public class User {
private String name;
private int age;
private Gender gender;
// getters and setters
}
ObjectMapper mapper = new ObjectMapper();
mapper.enable(SerializationFeature.INDENT_OUTPUT);
User user = new User();
user.setName("Tom");
user.setAge(20);
user.setGender(Gender.MALE);
String json = mapper.writeValueAsString(user);
System.out.println(json);
The output is as follows:
{
"name" : "Tom",
"age" : 20,
"gender" : "MALE"
}
In the above code, we first define a User
class , which contains a field of enumeration type gender
. We then use ObjectMapper
the class to User
serialize the object into a JSON string and print the result. As you can see, the value of the enumeration type has been serialized into a string type.
4. Serialize the Java time type
In practical applications, we often need to serialize Java time types into JSON strings for transmission to other systems or storage in databases. The Jackson library provides very convenient support for serializing Java 8 time types (such as
java.time.LocalDateTime
) into JSON strings.
Here's an example of Java time type serialization using the Jackson library:
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.databind.SerializationFeature;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
public class JacksonDemo {
public static void main(String[] args) throws Exception {
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new JavaTimeModule());
mapper.enable(SerializationFeature.INDENT_OUTPUT);
LocalDateTime now = LocalDateTime.now(ZoneId.of("Asia/Shanghai"));
String json = mapper.writeValueAsString(now);
System.out.println(json);
LocalDateTime parsed = mapper.readValue(json, LocalDateTime.class);
System.out.println(parsed.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));
}
}
In the above code, we first create a ObjectMapper
object and register JavaTimeModule
the module to support serialization of Java 8 time types. We then use LocalDateTime.now()
the method to get the current time and serialize it into a JSON string. Note that we use to ZoneId.of("Asia/Shanghai")
specify the time zone as Beijing time.
Next, we deserialize the JSON string into an object ObjectMapper
using themethod. Finally, we format the deserialized object into ISO-8601 time format and print it out.readValue()
LocalDateTime
The output is as follows:
"2022-02-23T14:25:23.845"
2022-02-23T14:25:23.845
As you can see, we successfully serialized the current time into a JSON string and restored the original time object when deserializing.
It should be noted that when serializing Java time types, the Jackson library uses the ISO-8601 time format by default. If you need to use other time formats, you can use the annotation to specify the time format. For example:@JsonFormat
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Shanghai")
private LocalDateTime startTime;
In the above code, we have specified the time format and time zone using @JsonFormat
the annotation . In this way, the Jackson library will use the specified time format for time serialization.
Five, basic type JSON deserialization
The basic way to convert a JSON string to a Java object is to
ObjectMapper
usereadValue
the method of the class. This method receives two parameters: a JSON string and a Java class, it will deserialize the JSON string into the specified Java class object.
1. Deserialize a single object
First, let's look at how to deserialize a JSON string into a single Java object. Suppose we have a JSON string representing an User
object :
{
"name": "Tom",
"age": 20
}
It can be deserialized into an object using the method of ObjectMapper
the class :readValue
User
ObjectMapper mapper = new ObjectMapper();
String json = "{\"name\":\"Tom\",\"age\":20}";
User user = mapper.readValue(json, User.class);
In the above code, we create ObjectMapper
an instance of the class and deserialize the JSON string into User
an object.
2. Deserialize collection objects
In addition to deserializing a single Java object, the Jackson library also supports deserializing Java collections, including
List
,Set
andMap
etc. A JSON string can be deserialized into a Java collection using the method ofObjectMapper
the class .readValue
ObjectMapper mapper = new ObjectMapper();
String json = "[{\"name\":\"Tom\",\"age\":20},{\"name\":\"Jerry\",\"age\":22}]";
List<User> users = mapper.readValue(json, new TypeReference<List<User>>() {});
In the code above, we created a JSON string containing two User
Objects and deserialized it into List
a collection.
It should be noted that due to Java's generic erasure mechanism, you cannot directly List<User>
pass to readValue
the method, and you need to use TypeReference
the class to specify the collection type. isTypeReference
a helper class provided by the Jackson library, which is used to obtain the type information of generic parameters.
3. Deserialize enumeration type
In Java, an enumeration type is a special data type that defines a fixed set of constants. In JSON data, strings are usually used to represent enumeration constants. Using the Jackson library can easily convert strings in JSON data to enumeration constants in Java.
The sample code is as follows:
First define an enumeration type:
public enum Gender {
MALE,
FEMALE
}
Then, suppose we have the following JSON data:
{
"name": "Tom",
"gender": "MALE"
}
We can convert strings in JSON data to enum constants in Java using the following code:
ObjectMapper mapper = new ObjectMapper();
String json = "{\"name\": \"Tom\", \"gender\": \"MALE\"}";
Map<String, Object> map = mapper.readValue(json, new TypeReference<Map<String, Object>>(){});
Gender gender = Gender.valueOf(map.get("gender").toString());
The above code first creates an object using the ObjectMapper class, and then parses the JSON data into a Map object. Finally, we can convert the strings in the Map to enum constants using the valueOf() method.
4. Deserialize Java time type
In Java, the time type is a very common data type, including Date, LocalDate, LocalTime, LocalDateTime, etc. In JSON data, time types are usually represented by strings. Using the Jackson library can easily convert strings in JSON data to time types in Java.
The sample code is as follows:
Suppose we have the following JSON data:
{
"name": "Tom",
"birthday": "2000-01-01"
}
We can use the following code to convert a string in JSON data to LocalDate type in Java:
ObjectMapper mapper = new ObjectMapper();
String json = "{\"name\": \"Tom\", \"birthday\": \"2000-01-01\"}";
Map<String, Object> map = mapper.readValue(json, new TypeReference<Map<String, Object>>(){});
LocalDate birthday = LocalDate.parse(map.get("birthday").toString());
The above code first creates an object using the ObjectMapper class, and then parses the JSON data into a Map object. Finally, we can use the parse() method to convert the strings in the Map to the LocalDate type. Deserialization of other time types is similar.
Six, custom serialization and deserialization
In some cases, the default serialization and deserialization behavior provided by the Jackson library may not meet the requirements, and custom serialization and deserialization rules are required. For example, when serializing
User
an object , we want to serialize the age as a string type instead of the default integer type.
1. Custom serialization
To customize serialization rules, you need to create a class that implements JsonSerializer
the interface . isJsonSerializer
an abstract class provided by the Jackson library, which is used to serialize Java objects into JSON strings.
Here is an example of serializing the age of an User
object as a string:
public class AgeToStringSerializer extends JsonSerializer<Integer> {
@Override
public void serialize(Integer value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
gen.writeString(value.toString());
}
}
In the above code, we defined a class AgeToStringSerializer
called , which inherits from JsonSerializer
the , and overrides serialize
the method . The method receives three parameters: the Java object to be serialized, JsonGenerator
the object , and an SerializerProvider
object that provides some information needed for serialization.
In serialize
the method , we value
convert the parameter to a string type and use gen.writeString
the method to write it JsonGenerator
into the object.
Next, we need User
to age
use @JsonSerialize
the annotation of the class to specify a custom AgeToStringSerializer
class for serialization:
public class User {
private String name;
@JsonSerialize(using = AgeToStringSerializer.class)
private int age;
private Address address;
// ...
}
Then, we can use ObjectMapper
the class to User
serialize the object into a JSON string as before:
ObjectMapper mapper = new ObjectMapper();
User user = new User("Tom", 20, new Address("New York", "NY"));
String json = mapper.writeValueAsString(user);
The resulting JSON string is as follows:
{"name":"Tom","age":"20","address":{"city":"New York","state":"NY"}}
2. Custom deserialization
Similar to custom serialization, to customize deserialization rules, you need to create a class that implements
JsonDeserializer
the interface . isJsonDeserializer
an abstract class provided by the Jackson library, which is used to deserialize JSON strings into Java objects.
Here is an example that deserializes the age of User
an object from a string type to an integer type:
public class StringToAgeDeserializer extends JsonDeserializer<Integer> {
@Override
public Integer deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
String value = p.getValueAsString();
return Integer.parseInt(value);
}
}
In the above code, we have defined a class StringToAgeDeserializer
called which inherits from JsonDeserializer
the class and overrides deserialize
the method . The method receives two parameters: the JsonParser
object and a DeserializationContext
object that provides some information needed when deserializing.
In deserialize
the method , we first use p.getValueAsString
the method to obtain the value in the JSON string and convert it to a string type. We then use Integer.parseInt
the method to convert the value of type string to type integer and return the result.
Next, we need User
to age
use @JsonDeserialize
the annotation of the class to specify a custom StringToAgeDeserializer
class for deserialization:
public class User {
private String name;
@JsonSerialize(using = AgeToStringSerializer.class)
@JsonDeserialize(using = StringToAgeDeserializer.class)
private int age;
private Address address;
// ...
}
Then, we can deserialize the JSON string into an object using ObjectMapper
the class User
:
ObjectMapper mapper = new ObjectMapper();
String json = "{\"name\":\"Tom\",\"age\":\"20\",\"address\":{\"city\":\"New York\",\"state\":\"NY\"}}";
User user = mapper.readValue(json, User.class);
In the above code, we first define a JSON string, and ObjectMapper
use readValue
the method of the class to deserialize it into User
an object . Since the value of age
the field is a string type, it will be StringToAgeDeserializer
parsed using our custom class during deserialization. In the end, we will get an User
object whose age
field value is 20 of integer type.
5. The purpose and usage of common annotations
1. @JsonProperty
The @JsonProperty annotation is used to specify the name of the property in the Java object when it is serialized into JSON data. If this annotation is not used, the name of the property is used by default. When deserializing, this annotation is also used to specify which property in the Java object the name of the property in the JSON data corresponds to.
The sample code is as follows:
Suppose we have the following Java object:
public class Person {
private String name;
private int age;
@JsonProperty("person_gender")
private Gender gender;
// getters and setters
}
We can use the @JsonProperty annotation to specify the name of the property, such as the gender property in the above code. When serializing this Java object into JSON data, the gender attribute will be serialized as a "person_gender" field.
ObjectMapper mapper = new ObjectMapper();
Person person = new Person();
person.setName("Tom");
person.setAge(20);
person.setGender(Gender.MALE);
String json = mapper.writeValueAsString(person);
System.out.println(json);
The output is:
{"name":"Tom","age":20,"person_gender":"MALE"}
2. @JsonFormat
The @JsonFormat annotation is used to specify the format of the date and time type in the Java object when it is serialized into JSON data. You can use this annotation to specify datetime format, time zone, etc.
The sample code is as follows:
Suppose we have the following Java object:
public class Person {
private String name;
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd")
private LocalDate birthday;
// getters and setters
}
We can use the @JsonFormat annotation to specify the date and time format, such as the birthday attribute in the above code. When serializing this Java object into JSON data, the birthday property will be serialized into a date string in the format "yyyy-MM-dd".
ObjectMapper mapper = new ObjectMapper();
Person person = new Person();
person.setName("Tom");
person.setBirthday(LocalDate.of(2000, 1, 1));
String json = mapper.writeValueAsString(person);
System.out.println(json);
The output is:
{"name":"Tom","birthday":"2000-01-01"}
3. @JsonIgnore
The @JsonIgnore annotation is used to ignore the operation of a property in a Java object during serialization and deserialization. Attributes marked with this annotation will not be included when serialized into JSON data, nor will they be assigned values when deserialized.
The sample code is as follows:
Suppose we have the following Java object:
public class Person {
private String name;
private int age;
@JsonIgnore
private Gender gender;
// getters and setters
}
We can use the @JsonIgnore annotation to ignore the gender attribute, which will not be included when serializing to JSON data.
ObjectMapper mapper = new ObjectMapper();
Person person = new Person();
person.setName("Tom");
person.setAge(20);
person.setGender(Gender.MALE);
String json = mapper.writeValueAsString(person);
System.out.println(json);
The output is:
{"name":"Tom","age":20}
4. @JsonInclude
The @JsonInclude annotation is used to specify the conditions for certain properties in the Java object to be serialized into JSON data, for example, if the property is null or the default value, the property is not included.
The sample code is as follows:
Suppose we have the following Java object:
@JsonInclude(JsonInclude.Include.NON_NULL)
public class Person {
private String name;
private Integer age;
private Gender gender;
// getters and setters
}
We can use the @JsonInclude annotation to specify that when serializing to JSON data, if the age attribute is null, the attribute will not be included.
ObjectMapper mapper = new ObjectMapper();
Person person = new Person();
person.setName("Tom");
person.setAge(null);
person.setGender(Gender.MALE);
String json = mapper.writeValueAsString(person);
System.out.println(json);
The output is:
{"name":"Tom","gender":"MALE"}
5. @JsonTypeInfo
The @JsonTypeInfo annotation is used to specify the type information of Java objects during serialization and deserialization. This annotation can be used to specify the actual type of the subclass, and the JSON data can be correctly converted to the corresponding Java object during deserialization.
The sample code is as follows:
Suppose we have the following Java object:
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type")
@JsonSubTypes({
@JsonSubTypes.Type(value = Dog.class, name = "dog"),
@JsonSubTypes.Type(value = Cat.class, name = "cat")
})
public abstract class Animal {
private String name;
// getters and setters
}
public class Dog extends Animal {
private String breed;
// getters and setters
}
public class Cat extends Animal {
private String color;
// getters and setters
}
We can use the @JsonTypeInfo annotation to specify the subclass type information of the Animal object, and the JSON data can be correctly converted into the corresponding Java object during serialization and deserialization.
ObjectMapper mapper = new ObjectMapper();
Animal dog = new Dog();
dog.setName("Bobby");
((Dog) dog).setBreed("Bulldog");
String json = mapper.writeValueAsString(dog);
System.out.println(json);
Animal animal = mapper.readValue("{\"name\":\"Kitty\",\"type\":\"cat\",\"color\":\"white\"}", Animal.class);
System.out.println(animal.getClass().getName());
System.out.println(((Cat) animal).getColor());
The output is:
{"type":"dog","name":"Bobby","breed":"Bulldog"}
com.example.jackson.Cat
white
Summarize
This article describes how to use the Jackson library for JSON serialization and deserialization. We first learned about the basic concepts and usage of the Jackson library, and then explained in detail how to use ObjectMapper
classes for serialization and deserialization. In the process of serialization and deserialization, we also introduced how to deal with date and collection types, and explained how to customize serialization and deserialization rules.
Using the Jackson library for JSON serialization and deserialization is a common operation in Java development. The content introduced in this article covers most of the usage of the Jackson library. I believe readers have a preliminary understanding of the Jackson library. In actual development, you can choose different serialization and deserialization methods according to your needs to better meet business needs.
If you think the content of this blog is helpful or inspiring to you, please follow my blog to get the latest technical articles and tutorials as soon as possible. At the same time, you are also welcome to leave a message in the comment area to share your thoughts and suggestions. Thank you for your support!