Maison  >  Article  >  Java  >  Comment SpringBoot intègre-t-il Jackson ?

Comment SpringBoot intègre-t-il Jackson ?

WBOY
WBOYavant
2023-05-12 21:01:041449parcourir

1. Introduction à Jackson

Description : Cet article parle de l'utilisation détaillée de Jackson La classe d'outils Jackson se trouve à la fin de l'article, vous. peut simplement le copier et le coller pour l'utiliser. Jackson est l'un des composants qui doivent être utilisés dans l'entreprise. Fastjson d'Alibaba est également couramment utilisé. Cependant, pour certaines raisons, il existe également de nombreux bugs et failles dans les entreprises qui prêtent attention à la sécurité. Gson (ça ne sert à rien) Mais je n'y connais pas grand chose). L'analyseur json par défaut de Spring MVC est Jackson. Jackson a de nombreux atouts. Jackson s'appuie sur moins de packages jar et est simple et facile à utiliser. Comparé à d'autres frameworks Java json tels que Gson, Jackson analyse les gros fichiers json plus rapidement ; Jackson utilise moins de mémoire pendant l'exécution et offre de meilleures performances ; Jackson dispose d'une API flexible qui peut être facilement étendue et personnalisée.

Connaissances supplémentaires :
Le nom du package de la version 1.x de Jackson est org.codehaus.jackson, org.codehaus.jackson
当升级到 2.x 版本时,包名变为com.fasterxml.jackson

Jackson 有三个核心包,分别是 StreamingDatabidAnnotations,通过这些包可以方便的对 JSON 进行操作.

  • jackson-core:核心包,提供基于"流模式"解析的相关 API,它包括 JsonPaser 和 JsonGenerator。 Jackson 内部实现正是通过高性能的流模式 API 的 JsonGenerator 和 JsonParser 来生成和解析 json。

  • jackson-annotations:注解包,提供标准注解功能.

  • jackson-databind :数据绑定包, 提供基于"对象绑定" 解析的相关 API ( ObjectMapper ) 和"树模型" 解析的相关 API (JsonNode);基于"对象绑定" 解析的 API 和"树模型"解析的 API 依赖基于"流模式"解析的 API。包含上面两个包,只导入这个坐标即可。

运行环境:

  • idea2020.2

  • jdk1.8

  • springboot 2.7.9Lors de la mise à niveau vers la version 2.x, le nom du package devient com.fasterxml.jackson.

  • Jackson propose trois packages principaux, à savoir Streaming, Databid et Annotations. Grâce à ces packages, vous pouvez facilement. JSON à utiliser
  • jackson-core : package de base, fournissant une analyse associée basée sur le "mode flux" API, qui inclut JsonPaser et JsonGenerator. L'implémentation interne de Jackson utilise JsonGenerator et JsonParser de l'API de streaming hautes performances pour générer et analyser JSON.

  • jackson-annotations : package d'annotation, fournissant des fonctions d'annotation standard. code>jackson-databind : package de liaison de données, fournissant des API associées basées sur l'analyse "Object Binding" (ObjectMapper) et des API associées à l'analyse "Tree Model" (JsonNode) basées sur l'analyse "Object Binding" L'API et " ; L'API d'analyse "modèle d'arbre" s'appuie sur l'API basée sur l'analyse "mode flux". Contient les deux packages ci-dessus, importez simplement ces coordonnées.

    Environnement de course :


    • idea2020.2
    • jdk1.8

    • springboot 2.7.9


      Télécharger la démo : Accédez simplement à mes ressources pour télécharger (instance Jackson - Ci-joint outils)

      2. Introduction à Json

      Comment SpringBoot intègre-t-il Jackson ?

      Description :

      En tant que développeur Java, vous devez apprendre Json, dans le front-end et projets de séparation back-end Parmi eux, Json est le format d'échange de données le plus courant. Par exemple, l'annotation @RequestBody dans SpringBoot est utilisée comme annotation pour recevoir le format Json. Lors de l'utilisation de Postman pour les tests, le raw-json transmis est également des données au format Json.

      Structure de représentation JSON : Object array

       : La structure de l'objet commence par des accolades "{" et se termine par des accolades "}", et la partie centrale se compose de 0 ou Il se compose de plusieurs paires "clé (mot-clé)/valeur (valeur)" séparées par ",". Les mots-clés et les valeurs sont séparés par ":". La structure syntaxique est comme le code. Voici un exemple.

      {
        "array": [1,2,3],
        "boolean": true,
        "name": "cllb",
        "null": null,
        "age": 12345,
        "object": {
          "height": 100,
          "color": "红色"
        },
        "string": "陈老老老板"
      }
      Comment SpringBoot intègre-t-il Jackson ?3. Springboot intègre Jackson

      1 Créer un projet

      Instructions :

      Créer un projet Springboot vide. (version 2.7.9). Je ne le répéterai pas trop ici. Il est très pratique de sélectionner le composant lombok lors de sa création, sans avoir à écrire la méthode Get/Set.

      Remarque :

      Vous pouvez voir que l'importation du package databind importera automatiquement les deux packages restants.

      2. Importer les coordonnées

      Description :

      Vous pouvez voir que l'importation du package databind importera automatiquement les deux packages restants.

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

      3. Fichier de configuration

      Comment SpringBoot intègre-t-il Jackson ?a. 🎜🎜#

      #指定日期格式,比如yyyy-MM-dd HH:mm:ss,或者具体的格式化类的全限定名
      spring.jackson.date-format
      #指定日期格式化时区,比如America/Los_Angeles或者GMT+10.
      spring.jackson.time-zone
      #是否开启Jackson的反序列化
      spring.jackson.deserialization
      #是否开启json的generators.
      spring.jackson.generator
      #指定Joda date/time的格式,比如yyyy-MM-ddHH:mm:ss). 如果没有配置的话,dateformat会作为backup
      spring.jackson.joda-date-time-format
      #指定json使用的Locale.
      spring.jackson.locale
      #是否开启Jackson通用的特性.
      spring.jackson.mapper
      #是否开启jackson的parser特性.
      spring.jackson.parser
      #指定PropertyNamingStrategy(CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORES)或者指定PropertyNamingStrategy子类的全限定类名.
      spring.jackson.property-naming-strategy
      #是否开启jackson的序列化.
      spring.jackson.serialization
      #指定序列化时属性的inclusion方式,具体查看JsonInclude.Include枚举.
      spring.jackson.serialization-inclusion

      yml format :

      spring:
        jackson:
          #日期格式化
          date-format: yyyy-MM-dd HH:mm:ss
          time-zone: GMT+8
          #设置空如何序列化
          default-property-inclusion: non_null    
          serialization:
             #格式化输出 
            indent_output: true
            #忽略无法转换的对象
            fail_on_empty_beans: false
          deserialization:
            #允许对象忽略json中不存在的属性
            fail_on_unknown_properties: false
          parser:
            #允许出现特殊字符和转义符
            allow_unquoted_control_chars: true
            #允许出现单引号
            allow_single_quotes: true

      b. Configuration personnalisée

      Instructions :

      Donnez directement la classe d'outil Jackson ici Tout le monde , la configuration personnalisée fait référence à l'affectation définie à object_mapper dans la classe d'outils. Il existe toutes les méthodes, et la démonstration s'effectue directement à l'aide de la classe d'outils.

      package com.clllb.jackson.utils;
      
      import com.fasterxml.jackson.annotation.JsonInclude;
      import com.fasterxml.jackson.core.JsonProcessingException;
      import com.fasterxml.jackson.core.type.TypeReference;
      import com.fasterxml.jackson.databind.*;
      import lombok.extern.slf4j.Slf4j;
      import org.springframework.util.StringUtils;
      
      import java.io.File;
      import java.io.IOException;
      import java.text.SimpleDateFormat;
      import java.util.List;
      
      @Slf4j
      public class JacksonUtil {
      
          private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
      
          private static final ObjectMapper OBJECT_MAPPER_SNAKE_CASE = new ObjectMapper();
          // 日期格式化
          private static final String STANDARD_FORMAT = "yyyy-MM-dd HH:mm:ss";
      
          static {
              //对象的所有字段全部列入
              OBJECT_MAPPER.setSerializationInclusion(JsonInclude.Include.ALWAYS);
              //取消默认转换timestamps形式
              OBJECT_MAPPER.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
              //忽略空Bean转json的错误
              OBJECT_MAPPER.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
              //所有的日期格式都统一为以下的样式,即yyyy-MM-dd HH:mm:ss
              OBJECT_MAPPER.setDateFormat(new SimpleDateFormat(STANDARD_FORMAT));
              //忽略 在json字符串中存在,但是在java对象中不存在对应属性的情况。防止错误
              OBJECT_MAPPER.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
          }
      
          static {
              //对象的所有字段全部列入
              OBJECT_MAPPER_SNAKE_CASE.setSerializationInclusion(JsonInclude.Include.ALWAYS);
              //取消默认转换timestamps形式
              OBJECT_MAPPER_SNAKE_CASE.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
              //忽略空Bean转json的错误
              OBJECT_MAPPER_SNAKE_CASE.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
              //所有的日期格式都统一为以下的样式,即yyyy-MM-dd HH:mm:ss
              OBJECT_MAPPER_SNAKE_CASE.setDateFormat(new SimpleDateFormat(STANDARD_FORMAT));
              //忽略 在json字符串中存在,但是在java对象中不存在对应属性的情况。防止错误
              OBJECT_MAPPER_SNAKE_CASE.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
              //转换为下划线
              OBJECT_MAPPER_SNAKE_CASE.setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE);
          }
      
          private JacksonUtil() {
          }
      
          /**
           * 对象转Json格式字符串
           *
           * @param obj 对象
           * @return Json格式字符串
           */
          public static <T> String obj2String(T obj) {
              if (obj == null) {
                  return null;
              }
              try {
                  return obj instanceof String ? (String) obj : OBJECT_MAPPER.writeValueAsString(obj);
              } catch (JsonProcessingException e) {
                  log.warn("Parse Object to String error : {}", e.getMessage());
                  return null;
              }
          }
      
          /**
           * 对象转file
           * @param fileName
           * @param obj
           */
           public static void obj2File(String fileName,Object obj){
              if (obj == null){
                  return;
              }
               try {
                   OBJECT_MAPPER.writeValue(new File(fileName),obj);
               } catch (IOException e) {
                   e.printStackTrace();
               }
           }
      
          /**
           * 对象转Json格式字符串; 属性名从驼峰改为下划线形式
           *
           * @param obj 对象
           * @return Json格式字符串
           */
          public static <T> String obj2StringFieldSnakeCase(T obj) {
              if (obj == null) {
                  return null;
              }
              try {
                  ObjectMapper objectMapper = OBJECT_MAPPER_SNAKE_CASE;
                  return obj instanceof String ? (String) obj : objectMapper.writeValueAsString(obj);
              } catch (JsonProcessingException e) {
                  log.warn("Parse Object to String error : {}", e.getMessage());
                  return null;
              }
          }
      
          /**
           * 字符串转换为自定义对象; 属性名从下划线形式改为驼峰
           *
           * @param str   要转换的字符串
           * @param clazz 自定义对象的class对象
           * @return 自定义对象
           */
          public static <T> T string2ObjFieldLowerCamelCase(String str, Class<T> clazz) {
              if (StringUtils.isEmpty(str) || clazz == null) {
                  return null;
              }
              try {
                  ObjectMapper objectMapper = OBJECT_MAPPER_SNAKE_CASE;
                  return clazz.equals(String.class) ? (T) str : objectMapper.readValue(str, clazz);
              } catch (Exception e) {
                  log.warn("Parse String to Object error : {}", e.getMessage());
                  return null;
              }
          }
      
          /**
           * 字符串转换为自定义对象(List); 属性名从下划线形式改为驼峰
           *
           * @param str           要转换的字符串
           * @param typeReference 自定义对象的typeReference List 对象
           * @return 自定义对象
           */
          public static <T> List<T> string2ListFieldLowerCamelCase(String str, TypeReference<List<T>> typeReference) {
              if (StringUtils.isEmpty(str) || typeReference == null) {
                  return null;
              }
              try {
                  ObjectMapper objectMapper = OBJECT_MAPPER_SNAKE_CASE;
                  return objectMapper.readValue(str, typeReference);
              } catch (Exception e) {
                  log.warn("Parse String to Object error : {}", e.getMessage());
                  return null;
              }
          }
      
          /**
           * 对象转Json格式字符串(格式化的Json字符串)
           *
           * @param obj 对象
           * @return 美化的Json格式字符串
           */
          public static <T> String obj2StringPretty(T obj) {
              if (obj == null) {
                  return null;
              }
              try {
                  return obj instanceof String ? (String) obj : OBJECT_MAPPER.writerWithDefaultPrettyPrinter().writeValueAsString(obj);
              } catch (JsonProcessingException e) {
                  log.warn("Parse Object to String error : {}", e.getMessage());
                  return null;
              }
          }
      
          /**
           * 字符串转换为自定义对象
           *
           * @param str   要转换的字符串
           * @param clazz 自定义对象的class对象
           * @return 自定义对象
           */
          public static <T> T string2Obj(String str, Class<T> clazz) {
              if (StringUtils.isEmpty(str) || clazz == null) {
                  return null;
              }
              try {
                  return clazz.equals(String.class) ? (T) str : OBJECT_MAPPER.readValue(str, clazz);
              } catch (Exception e) {
                  log.warn("Parse String to Object error : {}", e.getMessage());
                  return null;
              }
          }
      
          /**
           * 字符串转换为自定义字段转为list
           * @param str
           * @param typeReference
           * @param <T>
           * @return
           */
          public static <T> T string2Obj(String str, TypeReference<T> typeReference) {
              if (StringUtils.isEmpty(str) || typeReference == null) {
                  return null;
              }
              try {
                  return (T) (typeReference.getType().equals(String.class) ? str : OBJECT_MAPPER.readValue(str, typeReference));
              } catch (IOException e) {
                  log.warn("Parse String to Object error", e);
                  return null;
              }
          }
      
          public static <T> T string2Obj(String str, Class<?> collectionClazz, Class<?>... elementClazzes) {
              JavaType javaType = OBJECT_MAPPER.getTypeFactory().constructParametricType(collectionClazz, elementClazzes);
              try {
                  return OBJECT_MAPPER.readValue(str, javaType);
              } catch (IOException e) {
                  log.warn("Parse String to Object error : {}" + e.getMessage());
                  return null;
              }
          }
      }

      4. Classe d'entité

      Description :

      Créez une classe d'entité utilisateur ici

      package com.clllb.jackson.PO;
      
      import lombok.Data;
      
      import java.util.List;
      
      @Data
      public class User {
      
          private String username;
      
          private Integer age;
      
          private List<String> info;
      
      	private Long userId;
      }

      Exemple de projet : # 🎜🎜#

      5. Classe de test

      Instructions : Ajustez directement la classe d'outils dans la classe de test La méthode est très simple et les résultats sont joints.

      a.object conversion de type en Json

      Instructions : Comment SpringBoot intègre-t-il Jackson ? Utiliser la méthode writeValueAsString

        @Test
          void obj2string(){
              User user = new User();
              user.setUsername("clllb");
              user.setAge(24);
              user.setUserId(1L);
              List<String> infoList = new ArrayList<>();
              infoList.add("有一百万");
              infoList.add("发大财");
              user.setInfo(infoList);
      
              String json = JacksonUtil.obj2String(user);
              System.out.println(json);
          }

      Résultat de sortie : #🎜 🎜 #

      {"username":"clllb","age":24,"info":["un million","faire fortune"],"userId":1}# 🎜 🎜#b.type d'objet dans le fichier

      #🎜🎜##🎜🎜#Instructions : #🎜🎜# Utiliser la méthode writeValue #🎜🎜#
        @Test
          void obj2file(){
              User user = new User();
              user.setUsername("clllb");
              user.setAge(24);
              user.setUserId(1L);
              List<String> infoList = new ArrayList<>();
              infoList.add("有一百万");
              infoList.add("发大财");
              user.setInfo(infoList);
              String fileName = "ccccc";
              JacksonUtil.obj2File(fileName,user);
          }
      #🎜🎜#Résultat de sortie : # 🎜🎜##🎜🎜##🎜🎜##🎜🎜##🎜🎜#c.string tapez sur le type personnalisé d'objet #🎜🎜##🎜🎜##🎜🎜#Instructions : #🎜🎜# Utilisez la méthode readValue # 🎜🎜#
       @Test
          void string2obj(){
              String json = "{\"username\":\"clllb\",\"age\":24,\"info\":[\"有一百万\",\"发大财\"],\"userId\":11}";
              User user = JacksonUtil.string2Obj(json, User.class);
              System.out.println(user);
          }

      输出结果:

      User(username=clllb, age=24, info=[有一百万, 发大财], userId=11)

      d.string类型转Object自定义类型list

      说明: 使用readValue方法,传参变为TypeReference typeReference,这里工具类用的重载方法名是相同的。

      @Test
          void string2objList(){
              String json = "[{\"username\":\"clllb\",\"age\":24,\"info\":[\"有一百万\",\"发大财\"],\"userId\":11},\n" +
                      "{\"username\":\"陈老老老板\",\"age\":25,\"info\":[\"有一千万\",\"发大大财\"],\"userId\":12}]";
              List<User> user = JacksonUtil.string2Obj(json, new TypeReference<List<User>>(){});
              user.forEach(System.out::println);
          }

      输出结果:

      User(username=clllb, age=24, info=[有一百万, 发大财], userId=11)
      User(username=陈老老老板, age=25, info=[有一千万, 发大大财], userId=12)

      e.object类型转String(驼峰转下划线)

      说明: 使用writeValueAsString方法,这里区别看工具类就会发现,就是多了一个设置OBJECT_MAPPER_SNAKE_CASE.setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE);

       @Test
          void obj2sringSnakeCase(){
              User user = new User();
              user.setUsername("clllb");
              user.setAge(24);
              user.setUserId(11L);
              List<String> infoList = new ArrayList<>();
              infoList.add("有一百万");
              infoList.add("发大财");
              user.setInfo(infoList);
              String json = JacksonUtil.obj2StringFieldSnakeCase(user);
              System.out.println(json);
          }

      输出结果:

      {"username":"clllb","age":24,"info":["有一百万","发大财"],"user_id":11}

      f.string类型(下划线)转Object类型

      <font color = &#39;red&#39;><b>说明:</font> 使用readValue方法
      ```java
       @Test
          void string2obj(){
              String json = "{\"username\":\"clllb\",\"age\":24,\"info\":[\"有一百万\",\"发大财\"],\"user_id\":11}";
              User user = JacksonUtil.string2Obj(json, User.class);
              System.out.println(user);
          }

      输出结果:

      User(username=clllb, age=24, info=[有一百万, 发大财], userId=11)

      g.string类型(下划线)转Object自定义类型list

      说明: 使用readValue方法,传参变为TypeReference typeReference,这里工具类用的重载方法名是相同的。

       @Test
          void string2objSnakeCase(){
              String json = "[{\"username\":\"clllb\",\"age\":24,\"info\":[\"有一百万\",\"发大财\"],\"user_id\":11},\n" +
                      "{\"username\":\"陈老老老板\",\"age\":25,\"info\":[\"有一千万\",\"发大大财\"],\"user_id\":12}]";
              List<User> user = JacksonUtil.string2ListFieldLowerCamelCase(json, new TypeReference<List<User>>(){});
              user.forEach(System.out::println);
          }

      输出结果:

      User(username=clllb, age=24, info=[有一百万, 发大财], userId=11)
      User(username=陈老老老板, age=25, info=[有一千万, 发大大财], userId=12)

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer