最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

SpringBoot 定制化返回?cái)?shù)據(jù)的實(shí)現(xiàn)示例

 更新時(shí)間:2020年07月15日 08:32:18   作者:阿亮叨逼叨  
這篇文章主要介紹了SpringBoot 定制化返回?cái)?shù)據(jù)的實(shí)現(xiàn)示例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧

此時(shí)我們的返回結(jié)構(gòu)如下:

{
  "code": 200,
  "msg": "ok",
  "data": {
    "id": 1,
    "username": "steve",
    "secretKey": "xxx",
    "expiredAt": null,
    "createdAt": "2020-07-07T06:09:15"
  }
}

但上面有幾個(gè)問(wèn)題:

  •  我希望字段是以下劃線命名方式,也就是 createdAt 改成 created_at 這樣
  •  我希望某些字段值的輸出格式可以自定義,比如日期類型我希望輸出是 yyyy-MM-dd HH:mm:ss
  •  我不希望 secretKey 這類具有安全性質(zhì)的字段返回給調(diào)用方
  •  我不希望有 null 這樣的輸出,避免給調(diào)用方不必要的麻煩

定制字段名

我們有兩種選擇,第一種是在每一個(gè)字段上通過(guò)添加 @JsonProperty 注解來(lái)實(shí)現(xiàn),如下:

@JsonProperty("secret_key")
private String secretKey;

這種方式靈活度高,缺點(diǎn)就是繁瑣,變量名是單個(gè)單詞的不用轉(zhuǎn)換,多個(gè)單詞的如果要保持統(tǒng)一格式就需要每個(gè)都寫上,工作量不小。

第二種方式就是全局配置 Spring 內(nèi)置的 Jackson 的序列化轉(zhuǎn)換器,在 config 目錄下新建 JsonConfig.java 文件:

package com.foxescap.wxbox.config;

import com.fasterxml.jackson.databind.PropertyNamingStrategy;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import java.time.format.DateTimeFormatter;
import java.util.List;

/**
 * @author xfly
 */
@EnableWebMvc
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {

  @Bean
  public LocalDateTimeSerializer localDateTimeSerializer() {
    return new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
  }

  @Override
  public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
    converters.add(
        new MappingJackson2HttpMessageConverter(
            new Jackson2ObjectMapperBuilder()
                .propertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE)
                .build()
        )
    );
  }
}

我們通過(guò)重寫 WebMvcConfigurer 接口的 configureMessageConverters 方法,添加自定義的 JSON 轉(zhuǎn)換器,關(guān)鍵是 propertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE) 這行代碼,設(shè)置屬性的命名策略為下劃線命名方式。

定制字段值格式

最常見(jiàn)的就是對(duì)時(shí)間類型的字段格式化,也有兩種方式,第一種是在每個(gè)字段上添加 @JsonFormat 注解,比如格式化日期時(shí)間:

@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime expiredAt;

也可以全局配置,我們?cè)谏厦?JsonConfig 代碼的基礎(chǔ)上,加上一個(gè)類型串行器:

@Bean
public LocalDateTimeSerializer localDateTimeSerializer() {
  return new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
}

@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
  converters.add(
    new MappingJackson2HttpMessageConverter(
      new Jackson2ObjectMapperBuilder()
      .propertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE)
      .serializerByType(LocalDateTime.class, localDateTimeSerializer())
      .build()
    )
  );
}

這樣就能對(duì)全局 LocalDateTime 類型的字段序列化時(shí)轉(zhuǎn)換成我們自定義的格式了。

定制可見(jiàn)性

當(dāng)我們不需要有字段被序列化,即需要忽略它,那么可以在那個(gè)字段上添加 @JsonIgnore 注解即可。

處理 Null

一般地,要么是直接忽略值為 null 的字段,要么是將 null 轉(zhuǎn)換成空字符串處理,前者可以直接在每個(gè)需要的字段上加 @JsonInclude(Include.NON_NULL) 注解,或者也可以在每個(gè)需要序列化的類上加,當(dāng)然也可以全局配置,在 .build() 前加入 .serializationInclusion(JsonInclude.Include.NON_NULL) 即可。

如果我們不希望 null 值直接被忽略,又不需要直接給調(diào)用方返回 null,那么可以添加一個(gè) setNullValueSerializer 方法自定義輸出:

@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
  var builder = new Jackson2ObjectMapperBuilder()
    .propertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE)
    //.serializationInclusion(JsonInclude.Include.NON_NULL)
    .serializerByType(LocalDateTime.class, localDateTimeSerializer())
    .build();

  builder.getSerializerProvider()
    .setNullValueSerializer(new JsonSerializer<>() {
      @Override
      public void serialize(Object o, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
        jsonGenerator.writeString("");
      }
    });
  converters.add(new MappingJackson2HttpMessageConverter(builder));
}

糾結(jié)過(guò)是直接不序列化 Null 值還是設(shè)為空值,考慮到對(duì)于調(diào)用方,如果直接將 Null 值忽略了的話,數(shù)據(jù)的結(jié)構(gòu)完整性就大大破壞了,比如一個(gè)數(shù)組,有幾個(gè)數(shù)組元素里的字段有,有幾個(gè)沒(méi)有,對(duì)于調(diào)用方就非常不友好了。

如果你想對(duì)不同變量類型的 Null 值分別處理的話,那么就需要重寫 changeProperties 方法,比如對(duì)于數(shù)組集合類型的字段,如果是 Null 值則序列化成 [] ;如果是字符串類型的字段,序列化成 "" ;如果是不二類型的字段,序列化成 false 等等:

@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
  var builder = new Jackson2ObjectMapperBuilder()
    .propertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE)
    .serializerByType(LocalDateTime.class, localDateTimeSerializer())
    .build();

  builder.setSerializerFactory(builder.getSerializerFactory().withSerializerModifier(new BeanSerializerModifier() {
    @Override
    public List<BeanPropertyWriter> changeProperties(SerializationConfig config, BeanDescription beanDesc, List<BeanPropertyWriter> beanProperties) {
      for (var beanPropertyWriter : beanProperties) {
        var javaType = beanPropertyWriter.getType();
        if (javaType.isArrayType() || javaType.isCollectionLikeType()) {
          beanPropertyWriter.assignNullSerializer(new JsonSerializer<>() {
            @Override
            public void serialize(Object o, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
              jsonGenerator.writeStartArray();
              jsonGenerator.writeEndArray();
            }
          });
        } else if (javaType.isTypeOrSubTypeOf(String.class)) {
          beanPropertyWriter.assignNullSerializer(new JsonSerializer<>() {
            @Override
            public void serialize(Object value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
              gen.writeString("");
            }
          });
        } else if (javaType.isTypeOrSuperTypeOf(Boolean.class)) {
          beanPropertyWriter.assignNullSerializer(new JsonSerializer<>() {
            @Override
            public void serialize(Object value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
              gen.writeBoolean(false);
            }
          });
        } else if (javaType.isMapLikeType()) {
          beanPropertyWriter.assignNullSerializer(new JsonSerializer<>() {
            @Override
            public void serialize(Object value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
              gen.writeStartObject();
              gen.writeEndObject();
            }
          });
        } else if (javaType.isTypeOrSuperTypeOf(Integer.class) ||
              javaType.isTypeOrSuperTypeOf(Long.class) ||
              javaType.isTypeOrSuperTypeOf(Double.class) ||
              javaType.isTypeOrSuperTypeOf(Float.class)) {
          beanPropertyWriter.assignNullSerializer(new JsonSerializer<>() {
            @Override
            public void serialize(Object value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
              gen.writeNumber(0);
            }
          });
        } else if (javaType.isTypeOrSuperTypeOf(LocalDateTime.class) ||
              javaType.isTypeOrSuperTypeOf(LocalDate.class)) {
          beanPropertyWriter.assignNullSerializer(new JsonSerializer<>() {
            @Override
            public void serialize(Object value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
              gen.writeString("");
            }
          });
        }
      }

      return beanProperties;
    }
  }));

  converters.add(new MappingJackson2HttpMessageConverter(builder));
}

到此這篇關(guān)于SpringBoot 定制化返回?cái)?shù)據(jù)的實(shí)現(xiàn)示例的文章就介紹到這了,更多相關(guān)SpringBoot 定制化返回?cái)?shù)據(jù)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 詳解使用@RequestBody取POST方式的json字符串

    詳解使用@RequestBody取POST方式的json字符串

    這篇文章主要介紹了詳解使用@RequestBody取POST方式的json字符串,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-12-12
  • 基于spring mvc請(qǐng)求controller訪問(wèn)方式

    基于spring mvc請(qǐng)求controller訪問(wèn)方式

    這篇文章主要介紹了spring mvc請(qǐng)求controller訪問(wèn)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-09-09
  • Java垃圾回收機(jī)制的finalize方法實(shí)例分析

    Java垃圾回收機(jī)制的finalize方法實(shí)例分析

    這篇文章主要介紹了Java垃圾回收機(jī)制的finalize方法,結(jié)合實(shí)例形式分析了finalize方法的特點(diǎn)及在垃圾回收機(jī)制中的相關(guān)操作技巧,需要的朋友可以參考下
    2019-08-08
  • JVM內(nèi)存飆升線上問(wèn)題排查方式

    JVM內(nèi)存飆升線上問(wèn)題排查方式

    文章主要介紹了線上CMS服務(wù)內(nèi)存增長(zhǎng)問(wèn)題的排查過(guò)程,通過(guò)分析GC日志和堆??煺?定位問(wèn)題為Nacos的NamingService對(duì)象無(wú)法回收和MySQL的CallableStatement對(duì)象增長(zhǎng)迅速,最終通過(guò)將NamingService改為單例模式解決了內(nèi)存增長(zhǎng)問(wèn)題
    2025-03-03
  • Java線程讓步_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理

    Java線程讓步_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理

    yield()的作用是讓步。它能讓當(dāng)前線程由“運(yùn)行狀態(tài)”進(jìn)入到“就緒狀態(tài)”,從而讓其它具有相同優(yōu)先級(jí)的等待線程獲取執(zhí)行權(quán)。下面通過(guò)本文給大家介紹Java線程讓步的相關(guān)知識(shí),需要的朋友參考下吧
    2017-05-05
  • Java多線程并發(fā)編程 Volatile關(guān)鍵字

    Java多線程并發(fā)編程 Volatile關(guān)鍵字

    volatile 關(guān)鍵字是一個(gè)神秘的關(guān)鍵字,也許在 J2EE 上的 JAVA 程序員會(huì)了解多一點(diǎn),但在 Android 上的 JAVA 程序員大多不了解這個(gè)關(guān)鍵字。只要稍了解不當(dāng)就好容易導(dǎo)致一些并發(fā)上的錯(cuò)誤發(fā)生,例如好多人把 volatile 理解成變量的鎖
    2017-05-05
  • Java實(shí)現(xiàn)Web應(yīng)用中的定時(shí)任務(wù)(實(shí)例講解)

    Java實(shí)現(xiàn)Web應(yīng)用中的定時(shí)任務(wù)(實(shí)例講解)

    下面小編就為大家分享一篇Java實(shí)現(xiàn)Web 應(yīng)用中的定時(shí)任務(wù)的實(shí)例講解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2017-11-11
  • java?WebSocket?服務(wù)端實(shí)現(xiàn)代碼

    java?WebSocket?服務(wù)端實(shí)現(xiàn)代碼

    WebSocket協(xié)議是基于TCP的一種新的網(wǎng)絡(luò)協(xié)議。它實(shí)現(xiàn)了瀏覽器與服務(wù)器全雙工(full-duplex)通信——允許服務(wù)器主動(dòng)發(fā)送信息給客戶端,這篇文章主要介紹了java?WebSocket?服務(wù)端代碼,代碼簡(jiǎn)單易懂,對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-02-02
  • springboot logback如何從apollo配置中心讀取變量

    springboot logback如何從apollo配置中心讀取變量

    這篇文章主要介紹了springboot logback如何從apollo配置中心讀取變量的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-08-08
  • IntelliJ IDEA創(chuàng)建普通的Java 項(xiàng)目及創(chuàng)建 Java 文件并運(yùn)行的教程

    IntelliJ IDEA創(chuàng)建普通的Java 項(xiàng)目及創(chuàng)建 Java 文件并運(yùn)行的教程

    這篇文章主要介紹了IntelliJ IDEA創(chuàng)建普通的Java 項(xiàng)目及創(chuàng)建 Java 文件并運(yùn)行的教程,本文通過(guò)圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-02-02

最新評(píng)論

英超| 福建省| 高碑店市| 武城县| 新营市| 池州市| 玉环县| 万盛区| 正镶白旗| 淮滨县| 双城市| 德兴市| 景泰县| 舟山市| 五常市| 合肥市| 兴业县| 垣曲县| 丰台区| 佛坪县| 连州市| 宝兴县| 岚皋县| 孝义市| 柳州市| 天祝| 陕西省| 华宁县| 定边县| 大姚县| 清流县| 雅江县| 武强县| 民和| 安仁县| 棋牌| 襄樊市| 沅江市| 闻喜县| 务川| 玛纳斯县|