Serialización y deserialización JSON utilizando la biblioteca Jackson

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 clase​ObjectMapper​ 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 clase​JsonNode​ es una clase abstracta que representa un nodo JSON. La clase​JsonNode​ tiene múltiples subclases, como ​ObjectNode​​, ​ArrayNode​​,​, ​ValueNode​etc. , correspondientes a objetos, matrices y valores en JSON. La clase​JsonNode​ 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​utilizar ​writeValueAsString​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​y ​Map​etc. Una colección Java se puede serializar en una cadena JSON utilizando el método de ​ObjectMapper​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​utilizar ​readValue​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 de ​ObjectMapper​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. ​​Es​TypeReference​ 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 . ​​Es​JsonSerializer​ 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 . ​​Es​JsonDeserializer​ 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!

Supongo que te gusta

Origin blog.csdn.net/bairo007/article/details/132520849
Recomendado
Clasificación