首頁 > 軟體

springboot2中使用@JsonFormat註解不生效的解決

2022-02-18 19:00:37

使用@JsonFormat註解不生效

百度了不少解決方式,有讓用@JsonField,也有讓把fastjson去掉的,也有加很多設定的,但是都沒用。

本次使用的版本號

1、springboot2.2.2 ;

2、fastjson 1.1.26

3、<jackson-mapper-asl.version>1.9.10</jackson-mapper-asl.version>     
<jackson-core.version>2.10.3</jackson-core.version>

第三點以及相關的依賴可能不需要,加上也沒關係

pom檔案中的依賴:

<dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>${fastjson.version}</version>
        </dependency>
<dependency>
            <groupId>org.codehaus.jackson</groupId>
            <artifactId>jackson-mapper-asl</artifactId>
            <version>${jackson-mapper-asl.version}</version>
        </dependency> 
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-core</artifactId>
            <version>${jackson-core.version}</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>${jackson-core.version}</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-annotations</artifactId>
            <version>${jackson-core.version}</version>
        </dependency>

解決方式

第一步新建一個轉換類 用於自定義Jackson反序列化日期型別時應用的型別轉換器,一般用於@RequestBody接受引數時使用

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateUtils;
 
import java.io.IOException;
import java.text.ParseException;
import java.util.Date;
 
/**
 * 自定義Jackson反序列化日期型別時應用的型別轉換器,一般用於@RequestBody接受引數時使用
 *  次類是借用網上別的人的,增加了一個日期格式化的型別
 */
public class DateJacksonConverter extends JsonDeserializer<Date> {
    //此處尤為重要,請查詢自己控制檯報錯的日期格式化型別是啥樣的
    //我的是2020-04-29T16:23:44.999Z 所以我在下面的陣列中新增了 "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'" 格式;如果下面陣列中沒有你要的格式化型別,其他的可自行根據自己的情況去新增即可
    private static String[] pattern =
            new String[]{"yyyy-MM-dd", "yyyy-MM-dd HH:mm", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm:ss.S",
                    "yyyy.MM.dd", "yyyy.MM.dd HH:mm", "yyyy.MM.dd HH:mm:ss", "yyyy.MM.dd HH:mm:ss.S",
                    "yyyy/MM/dd", "yyyy/MM/dd HH:mm", "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd HH:mm:ss.S", "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"};
 
    @Override
    public Date deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
 
        Date targetDate = null;
        String originDate = p.getText();
        if (StringUtils.isNotEmpty(originDate)) {
            try {
                long longDate = Long.valueOf(originDate.trim());
                targetDate = new Date(longDate);
            } catch (NumberFormatException e) {
                try {
                    targetDate = DateUtils.parseDate(originDate, DateJacksonConverter.pattern);
                } catch (ParseException pe) {
                    throw new IOException(String.format(
                            "'%s' can not convert to type 'java.util.Date',just support timestamp(type of long) and following date format(%s)",
                            originDate,
                            StringUtils.join(pattern, ",")));
                }
            }
        } 
        return targetDate;
    } 
    @Override
    public Class<?> handledType() {
        return Date.class;
    }
}

建立好上邊的類之後,如果不想繼續,則可以在實體物件屬性上加註解就完全可以了。

匯入的包路徑為:

import com.fasterxml.jackson.databind.annotation.JsonDeserialize; 
@JsonDeserialize(using=DateJacksonConverter.class)
private Date startDate;

如果不想去讓實體類加這個註解,可以在寫一個公共設定,如下:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
 
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fx.base.serializer.DateJacksonConverter;
 
@Configuration
public class ConverterConfig {
    @Bean
    public DateJacksonConverter dateJacksonConverter() {
        return new DateJacksonConverter();
    }
 
    @Bean
    public Jackson2ObjectMapperFactoryBean jackson2ObjectMapperFactoryBean(
            @Autowired
                    DateJacksonConverter dateJacksonConverter) {
        Jackson2ObjectMapperFactoryBean jackson2ObjectMapperFactoryBean = new Jackson2ObjectMapperFactoryBean();
 
        jackson2ObjectMapperFactoryBean.setDeserializers(dateJacksonConverter);
        return jackson2ObjectMapperFactoryBean;
    }
 
    @Bean
    public MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter(
            @Autowired
                    ObjectMapper objectMapper) {
        MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter =
                new MappingJackson2HttpMessageConverter();
        mappingJackson2HttpMessageConverter.setObjectMapper(objectMapper);
        return mappingJackson2HttpMessageConverter;
    }
}

此時就不必再每個實體類屬性上加註解了。

@JsonFormat和@DateTimeFormat的作用

  • @DatetimeFormat是將String轉換成Date,一般前臺給後臺傳值時用
    import org.springframework.format.annotation.DateTimeFormat;
    /**
     * 前臺傳後臺時, 字串自動封裝成日期
     */
    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date birth;
  • @JsonFormat(pattern=”yyyy-MM-dd”) 將Date轉換成String 一般後臺傳值給前臺時
    import com.fasterxml.jackson.annotation.JsonFormat;
    /**
     * 後臺返給前臺時, 日期自動格式化
     */
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date birth;

注意:

@JsonFormat不僅可以完成後臺到前臺引數傳遞的型別轉換,還可以實現前臺到後臺型別轉換。

當content-type為application/json時,優先使用@JsonFormat的pattern進行型別轉換。而不會使用@DateTimeFormat進行型別轉換。

@JsonFormat註解的作用就是完成json字串到java物件的轉換工作,與引數傳遞的方向無關。

以上為個人經驗,希望能給大家一個參考,也希望大家多多支援it145.com。


IT145.com E-mail:sddin#qq.com