Si cree que el contenido de este blog es útil o inspirador para usted, siga mi blog para obtener los últimos artículos técnicos y tutoriales lo antes posible. Al mismo tiempo, también puedes dejar un mensaje en el área de comentarios para compartir tus pensamientos y sugerencias. ¡Gracias por tu apoyo!
1. Preámbulo
En el desarrollo web moderno, JSON (JavaScript Object Notation) se ha convertido en un formato de datos ampliamente utilizado para la transmisión y el almacenamiento de datos de front-end y back-end. Java es un lenguaje de programación orientado a objetos y JSON son datos en un formato de par clave-valor, por lo que en Java, debe convertir un objeto Java en una cadena JSON o convertir una cadena JSON en un objeto Java. Este proceso es la serialización y deserialización de JSON.
Para la serialización y deserialización JSON en Java, existen muchas bibliotecas de código abierto para elegir, de las cuales la biblioteca Jackson es una de las más populares. La biblioteca Jackson proporciona una gran cantidad de funciones para la serialización y deserialización JSON flexible con un rendimiento excelente.
Este artículo presentará la serialización y deserialización JSON de la biblioteca Jackson, incluida la serialización y deserialización de objetos básicos, colecciones, tipos personalizados, tipos de enumeración y tipos de tiempo Java. Este artículo tiene como objetivo permitir a los lectores comprender y utilizar rápidamente la biblioteca Jackson para la serialización y deserialización JSON.
2. ¿Qué es la serialización y deserialización JSON?
La serialización JSON es el proceso de convertir un objeto Java en una cadena JSON. Durante el proceso de serialización JSON, las propiedades del objeto Java se convertirán en pares clave-valor del objeto JSON. Si el objeto Java contiene otros objetos o colecciones Java, estos objetos anidados también se convertirán en objetos JSON anidados y matrices JSON. .
La deserialización JSON es el proceso de convertir una cadena JSON en un objeto Java. Durante el proceso de deserialización JSON, los pares clave-valor del objeto JSON se convertirán a las propiedades del objeto Java. Si el objeto JSON contiene otros objetos JSON o matrices JSON, estos JSON anidados también se convertirán en objetos Java anidados y Colecciones Java.
Tres, introducción a la biblioteca Jackson
La biblioteca Jackson es una biblioteca de procesamiento JSON basada en Java, que proporciona un analizador JSON flexible y un generador JSON, que puede convertir fácilmente objetos Java y datos JSON. La biblioteca Jackson es muy sencilla de usar y tiene un rendimiento excelente, por lo que se utiliza ampliamente en el desarrollo de Java.
La biblioteca de Jackson tiene dos clases principales: ObjectMapper
y JsonNode
.
La claseObjectMapper
es la clase más importante en la biblioteca Jackson, que proporciona la conversión entre serialización y deserialización de objetos Java y JSON. ObjectMapper
Las instancias de la clase
La claseJsonNode
es una clase abstracta que representa un nodo JSON. La claseJsonNode
tiene múltiples subclases, como ObjectNode
, ArrayNode
,, ValueNode
etc. , correspondientes a objetos, matrices y valores en JSON. La claseJsonNode
proporciona métodos convenientes para leer el valor de un nodo JSON.
4. Serialización JSON de tipo básico
1. Serialización de objetos
La forma más básica de convertir un objeto Java en una cadena JSON es
ObjectMapper
utilizarwriteValueAsString
el método de la clase. Este método recibe un objeto Java como parámetro y devuelve una cadena JSON.
Por ejemplo:
ObjectMapper mapper = new ObjectMapper();
User user = new User("Tom", 20);
String json = mapper.writeValueAsString(user);
En el código anterior, creamos un User
objeto y usamos ObjectMapper
la clase para serializarlo en una cadena JSON. User
La definición de la clase
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;
}
}
La cadena JSON resultante es la siguiente:
{"name":"Tom","age":20}
2. Serialización de colecciones
Además de serializar un único objeto Java, la biblioteca Jackson también admite la serialización de colecciones Java, incluidas
List
,Set
yMap
etc. Una colección Java se puede serializar en una cadena JSON utilizando el método deObjectMapper
la clase .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);
En el código anterior, creamos una List
colección y User
agregamos dos objetos a la colección, y luego usamos ObjectMapper
la clase para serializar la colección en una cadena JSON.
La cadena JSON resultante es la siguiente:
[{"name":"Tom","age":20},{"name":"Jerry","age":22}]
3. Tipo de enumeración serializada
En Java, un tipo de enumeración es un tipo de datos común, que normalmente se utiliza para representar un conjunto limitado de valores. Serializar un tipo de enumeración en una cadena JSON utilizando la biblioteca Jackson también es una operación común. Aquí está la definición de un tipo enumerado simple:
public enum Gender {
MALE, FEMALE
}
Para serializar un tipo de enumeración en una cadena JSON, solo necesitamos agregar @JsonFormat
la anotación y especificar el formato de serialización. Por ejemplo, el siguiente código serializará un tipo de enumeración usando letras mayúsculas:
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);
El resultado es el siguiente:
{
"name" : "Tom",
"age" : 20,
"gender" : "MALE"
}
En el código anterior, primero definimos una User
clase , que contiene un campo de tipo de enumeración gender
. Luego usamos ObjectMapper
la clase para User
serializar el objeto en una cadena JSON e imprimir el resultado. Como puede ver, el valor del tipo de enumeración se ha serializado en un tipo de cadena.
4. Serializar el tipo de hora de Java
En aplicaciones prácticas, a menudo necesitamos serializar tipos de tiempo Java en cadenas JSON para transmitirlos a otros sistemas o almacenarlos en bases de datos. La biblioteca Jackson proporciona un soporte muy conveniente para serializar tipos de tiempo de Java 8 (como
java.time.LocalDateTime
) en cadenas JSON.
A continuación se muestra un ejemplo de serialización de tipos de tiempo de Java utilizando la biblioteca Jackson:
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));
}
}
En el código anterior, primero creamos un ObjectMapper
objeto y registramos JavaTimeModule
el módulo para admitir la serialización de tipos de tiempo de Java 8. Luego usamos LocalDateTime.now()
el método para obtener la hora actual y serializarla en una cadena JSON. Tenga en cuenta que utilizamos para ZoneId.of("Asia/Shanghai")
especificar la zona horaria como hora de Beijing.
A continuación, deserializamos la cadena JSON en un objeto ObjectMapper
usando el método. Finalmente, formateamos el objeto deserializado en formato de hora ISO-8601 y lo imprimimos.readValue()
LocalDateTime
El resultado es el siguiente:
"2022-02-23T14:25:23.845"
2022-02-23T14:25:23.845
Como puede ver, serializamos con éxito la hora actual en una cadena JSON y restauramos el objeto de hora original al deserializar.
Cabe señalar que al serializar tipos de hora Java, la biblioteca Jackson utiliza el formato de hora ISO-8601 de forma predeterminada. Si necesita utilizar otros formatos de hora, puede utilizar la anotación para especificar el formato de hora. Por ejemplo:@JsonFormat
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss", timezone = "Asia/Shanghai")
private LocalDateTime startTime;
En el código anterior, hemos especificado el formato de hora y la zona horaria usando @JsonFormat
la anotación . De esta manera, la biblioteca Jackson utilizará el formato de hora especificado para la serialización de la hora.
Cinco, deserialización JSON de tipo básico
La forma básica de convertir una cadena JSON en un objeto Java es
ObjectMapper
utilizarreadValue
el método de la clase. Este método recibe dos parámetros: una cadena JSON y una clase Java; deserializará la cadena JSON en el objeto de clase Java especificado.
1. Deserializar un solo objeto
Primero, veamos cómo deserializar una cadena JSON en un único objeto Java. Supongamos que tenemos una cadena JSON que representa un User
objeto :
{
"name": "Tom",
"age": 20
}
Se puede deserializar en un objeto usando el método de ObjectMapper
la clase :readValue
User
ObjectMapper mapper = new ObjectMapper();
String json = "{\"name\":\"Tom\",\"age\":20}";
User user = mapper.readValue(json, User.class);
En el código anterior, creamos ObjectMapper
una instancia de la clase y deserializamos la cadena JSON en User
un objeto.
2. Deserializar los objetos de la colección.
Además de deserializar un único objeto Java, la biblioteca Jackson también admite la deserializar colecciones de Java, incluidas
List
,Set
y,Map
etc. Una cadena JSON se puede deserializar en una colección Java utilizando el método deObjectMapper
la clase .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>>() {});
En el código anterior, creamos una cadena JSON que contiene dos User
objetos y la deserializamos en List
una colección.
Cabe señalar que debido al mecanismo de borrado genérico de Java, no puede List<User>
pasar readValue
al método y debe usar TypeReference
la clase para especificar el tipo de colección. EsTypeReference
una clase auxiliar proporcionada por la biblioteca Jackson, que se utiliza para obtener información de tipo de parámetros genéricos.
3. Deserializar el tipo de enumeración
En Java, un tipo de enumeración es un tipo de datos especial que define un conjunto fijo de constantes. En los datos JSON, las cadenas se suelen utilizar para representar constantes de enumeración. El uso de la biblioteca Jackson puede convertir fácilmente cadenas de datos JSON en constantes de enumeración en Java.
El código de muestra es el siguiente:
Primero defina un tipo de enumeración:
public enum Gender {
MALE,
FEMALE
}
Entonces, supongamos que tenemos los siguientes datos JSON:
{
"name": "Tom",
"gender": "MALE"
}
Podemos convertir cadenas en datos JSON en constantes de enumeración en Java usando el siguiente código:
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());
El código anterior primero crea un objeto usando la clase ObjectMapper y luego analiza los datos JSON en un objeto Map. Finalmente, podemos convertir las cadenas en el Mapa en constantes de enumeración usando el método valueOf().
4. Deserializar el tipo de hora de Java
En Java, el tipo de hora es un tipo de datos muy común, que incluye Fecha, LocalDate, LocalTime, LocalDateTime, etc. En los datos JSON, los tipos de tiempo suelen estar representados por cadenas. El uso de la biblioteca Jackson puede convertir fácilmente cadenas de datos JSON a tipos de tiempo en Java.
El código de muestra es el siguiente:
Supongamos que tenemos los siguientes datos JSON:
{
"name": "Tom",
"birthday": "2000-01-01"
}
Podemos usar el siguiente código para convertir una cadena en datos JSON al tipo LocalDate en 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());
El código anterior primero crea un objeto usando la clase ObjectMapper y luego analiza los datos JSON en un objeto Map. Finalmente, podemos usar el método parse() para convertir las cadenas en el Mapa al tipo LocalDate. La deserialización de otros tipos de tiempo es similar.
Seis, serialización y deserialización personalizadas
En algunos casos, es posible que el comportamiento predeterminado de serialización y deserialización proporcionado por la biblioteca Jackson no cumpla con los requisitos y se requieren reglas personalizadas de serialización y deserialización. Por ejemplo, al serializar
User
un objeto , queremos serializar la edad como un tipo de cadena en lugar del tipo entero predeterminado.
1. Serialización personalizada
Para personalizar las reglas de serialización, debe crear una clase que implemente JsonSerializer
la interfaz . EsJsonSerializer
una clase abstracta proporcionada por la biblioteca Jackson y se utiliza para serializar objetos Java en cadenas JSON.
A continuación se muestra un ejemplo de cómo serializar la edad de un User
objeto como una cadena:
public class AgeToStringSerializer extends JsonSerializer<Integer> {
@Override
public void serialize(Integer value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
gen.writeString(value.toString());
}
}
En el código anterior, definimos una clase AgeToStringSerializer
llamada , que hereda JsonSerializer
del método y anula serialize
el método . El método recibe tres parámetros: el objeto Java que se va a serializar, JsonGenerator
el objeto y un SerializerProvider
objeto que proporciona cierta información necesaria para la serialización.
En serialize
el método , value
convertimos el parámetro a un tipo de cadena y usamos gen.writeString
el método para escribirlo JsonGenerator
en el objeto.
A continuación, User
necesitamos age
usar @JsonSerialize
la anotación de la clase para especificar una AgeToStringSerializer
clase personalizada para la serialización:
public class User {
private String name;
@JsonSerialize(using = AgeToStringSerializer.class)
private int age;
private Address address;
// ...
}
Luego, podemos usar ObjectMapper
la clase para User
serializar el objeto en una cadena JSON como antes:
ObjectMapper mapper = new ObjectMapper();
User user = new User("Tom", 20, new Address("New York", "NY"));
String json = mapper.writeValueAsString(user);
La cadena JSON resultante es la siguiente:
{"name":"Tom","age":"20","address":{"city":"New York","state":"NY"}}
2. Deserialización personalizada
De manera similar a la serialización personalizada, para personalizar las reglas de deserialización, debe crear una clase que implemente
JsonDeserializer
la interfaz . EsJsonDeserializer
una clase abstracta proporcionada por la biblioteca Jackson y se utiliza para deserializar cadenas JSON en objetos Java.
A continuación se muestra un ejemplo que deserializa la antigüedad de User
un objeto de un tipo de cadena a un tipo de entero:
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);
}
}
En el código anterior, hemos definido una clase StringToAgeDeserializer
llamada que hereda de JsonDeserializer
la clase y anula deserialize
el método . El método recibe dos parámetros: el JsonParser
objeto y un DeserializationContext
objeto que proporciona cierta información necesaria al deserializar.
En deserialize
el método , primero usamos p.getValueAsString
el método para obtener el valor en la cadena JSON y convertirlo a un tipo de cadena. Luego usamos Integer.parseInt
el método para convertir el valor de tipo cadena a tipo entero y devolver el resultado.
A continuación, User
necesitamos age
usar @JsonDeserialize
la anotación de la clase para especificar una StringToAgeDeserializer
clase personalizada para la deserialización:
public class User {
private String name;
@JsonSerialize(using = AgeToStringSerializer.class)
@JsonDeserialize(using = StringToAgeDeserializer.class)
private int age;
private Address address;
// ...
}
Luego, podemos deserializar la cadena JSON en un objeto usando ObjectMapper
la clase User
:
ObjectMapper mapper = new ObjectMapper();
String json = "{\"name\":\"Tom\",\"age\":\"20\",\"address\":{\"city\":\"New York\",\"state\":\"NY\"}}";
User user = mapper.readValue(json, User.class);
En el código anterior, primero definimos una cadena JSON y ObjectMapper
usamos readValue
el método de la clase para deserializarla en User
un objeto . Dado que el valor del age
campo es un tipo de cadena, se StringToAgeDeserializer
analizará utilizando nuestra clase personalizada durante la deserialización. Al final, obtendremos un User
objeto cuyo age
valor de campo es 20 de tipo entero.
5. Propósito y uso de anotaciones comunes.
1. @JsonProperty
La anotación @JsonProperty se utiliza para especificar el nombre de la propiedad en el objeto Java cuando se serializa en datos JSON. Si no se utiliza esta anotación, el nombre de la propiedad se utiliza de forma predeterminada. Al deserializar, esta anotación también se utiliza para especificar a qué propiedad del objeto Java corresponde el nombre de la propiedad en los datos JSON.
El código de muestra es el siguiente:
Supongamos que tenemos el siguiente objeto Java:
public class Person {
private String name;
private int age;
@JsonProperty("person_gender")
private Gender gender;
// getters and setters
}
Podemos usar la anotación @JsonProperty para especificar el nombre de la propiedad, como la propiedad de género en el código anterior. Al serializar este objeto Java en datos JSON, el atributo de género se serializará como un campo "person_gender".
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);
La salida es:
{"name":"Tom","age":20,"person_gender":"MALE"}
2. @JsonFormat
La anotación @JsonFormat se utiliza para especificar el formato del tipo de fecha y hora en el objeto Java cuando se serializa en datos JSON. Puede utilizar esta anotación para especificar el formato de fecha y hora, la zona horaria, etc.
El código de muestra es el siguiente:
Supongamos que tenemos el siguiente objeto Java:
public class Person {
private String name;
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd")
private LocalDate birthday;
// getters and setters
}
Podemos usar la anotación @JsonFormat para especificar el formato de fecha y hora, como el atributo de cumpleaños en el código anterior. Al serializar este objeto Java en datos JSON, la propiedad de cumpleaños se serializará en una cadena de fecha en el formato "aaaa-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);
La salida es:
{"name":"Tom","birthday":"2000-01-01"}
3. @JsonIgnorar
La anotación @JsonIgnore se utiliza para ignorar la operación de una propiedad en un objeto Java durante la serialización y deserialización. Los atributos marcados con esta anotación no se incluirán cuando se serialicen en datos JSON, ni se les asignarán valores cuando se deserialicen.
El código de muestra es el siguiente:
Supongamos que tenemos el siguiente objeto Java:
public class Person {
private String name;
private int age;
@JsonIgnore
private Gender gender;
// getters and setters
}
Podemos usar la anotación @JsonIgnore para ignorar el atributo de género, que no se incluirá al serializar datos JSON.
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);
La salida es:
{"name":"Tom","age":20}
4. @JsonIncluir
La anotación @JsonInclude se utiliza para especificar las condiciones para que ciertas propiedades en el objeto Java se serialicen en datos JSON; por ejemplo, si la propiedad es nula o el valor predeterminado, la propiedad no se incluye.
El código de muestra es el siguiente:
Supongamos que tenemos el siguiente objeto Java:
@JsonInclude(JsonInclude.Include.NON_NULL)
public class Person {
private String name;
private Integer age;
private Gender gender;
// getters and setters
}
Podemos usar la anotación @JsonInclude para especificar que al serializar datos JSON, si el atributo de edad es nulo, el atributo no se incluirá.
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);
La salida es:
{"name":"Tom","gender":"MALE"}
5. @JsonTypeInfo
La anotación @JsonTypeInfo se utiliza para especificar la información de tipo de objetos Java durante la serialización y deserialización. Esta anotación se puede utilizar para especificar el tipo real de la subclase y los datos JSON se pueden convertir correctamente al objeto Java correspondiente durante la deserialización.
El código de muestra es el siguiente:
Supongamos que tenemos el siguiente objeto Java:
@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
}
Podemos usar la anotación @JsonTypeInfo para especificar la información del tipo de subclase del objeto Animal, y los datos JSON se pueden convertir correctamente en el objeto Java correspondiente durante la serialización y deserialización.
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());
La salida es:
{"type":"dog","name":"Bobby","breed":"Bulldog"}
com.example.jackson.Cat
white
Resumir
Este artículo describe cómo utilizar la biblioteca Jackson para la serialización y deserialización JSON. Primero aprendimos sobre los conceptos básicos y el uso de la biblioteca Jackson, y luego explicamos en detalle cómo usar ObjectMapper
clases para la serialización y deserialización. En el proceso de serialización y deserialización, también presentamos cómo manejar la fecha y los tipos de colección, y explicamos cómo personalizar las reglas de serialización y deserialización.
El uso de la biblioteca Jackson para la serialización y deserialización JSON es una operación común en el desarrollo de Java. El contenido presentado en este artículo cubre la mayor parte del uso de la biblioteca de Jackson. Creo que los lectores tienen una comprensión preliminar de la biblioteca de Jackson. En el desarrollo real, puede elegir diferentes métodos de serialización y deserialización según sus necesidades para satisfacer mejor las necesidades comerciales.
Si cree que el contenido de este blog es útil o inspirador para usted, siga mi blog para obtener los últimos artículos técnicos y tutoriales lo antes posible. Al mismo tiempo, también puedes dejar un mensaje en el área de comentarios para compartir tus pensamientos y sugerencias. ¡Gracias por tu apoyo!