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

SpringBoot中Jackson ObjectMapper應(yīng)用及說明

 更新時間:2026年05月28日 09:33:46   作者:JAVA@架構(gòu)  
SpringBoot支持支持Jackson作為默認的JSON映射庫,提供便捷的對象與JSON轉(zhuǎn)換功能,文章詳細介紹了ObjectMapper的配置與使用,以及SpringBoot中Jackson的多種自定義配置方法

Spring Boot支持與三種JSON mapping庫集成:Gson、Jackson和JSON-B。

Jackson是首選和默認的。

Jackson是spring-boot-starter-json的一部分,spring-boot-starter-web中包含spring-boot-starter-json。也就是說,當(dāng)項目中引入spring-boot-starter-web后會自動引入spring-boot-starter-json。

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

ObjectMapper

ObjectMapper是jackson-databind包中的一個類,提供讀寫JSON的功能,可以方便的進行對象和JSON轉(zhuǎn)換:

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.IOException;
public final class JsonUtil {
    private static ObjectMapper mapper = new ObjectMapper();
    private JsonUtil() {
    }
    /**
     * Serialize any Java value as a String.
     */
    public static String generate(Object object) throws JsonProcessingException {
        return mapper.writeValueAsString(object);
    }
    /**
     * Deserialize JSON content from given JSON content String.
     */
    public static <T> T parse(String content, Class<T> valueType) throws IOException {
        return mapper.readValue(content, valueType);
    }
}

編寫一簡單POJO測試類:

import java.util.Date;
public class Hero {
    public static void main(String[] args) throws Exception {
        System.out.println(JsonUtil.generate(new Hero("Jason", new Date())));
    }
    private String name;
    private Date birthday;
    public Hero() {
    }
    public Hero(String name, Date birthday) {
        this.name = name;
        this.birthday = birthday;
    }
    public String getName() {
        return name;
    }
    public Date getBirthday() {
        return birthday;
    }
}

運行后輸出結(jié)果如下:

{"name":"Jason","birthday":1540909420353}

可以看到日期轉(zhuǎn)換為長整型。

ObjectMapper默認序列化配置啟用了SerializationFeature.WRITE_DATES_AS_TIMESTAMPS,日期將轉(zhuǎn)換為Timestamp。

可查看如下源碼:

public ObjectMapper(JsonFactory jf, DefaultSerializerProvider sp, DefaultDeserializationContext dc) {
...
    BaseSettings base = DEFAULT_BASE.withClassIntrospector(defaultClassIntrospector());
    _configOverrides = new ConfigOverrides();
    _serializationConfig = new SerializationConfig(base, _subtypeResolver, mixins, rootNames, _configOverrides);
    ...
}
public SerializationConfig(BaseSettings base, SubtypeResolver str, SimpleMixInResolver mixins, RootNameLookup rootNames,
        ConfigOverrides configOverrides)
{
    super(base, str, mixins, rootNames, configOverrides);
    _serFeatures = collectFeatureDefaults(SerializationFeature.class);
    _filterProvider = null;
    _defaultPrettyPrinter = DEFAULT_PRETTY_PRINTER;
    _generatorFeatures = 0;
    _generatorFeaturesToChange = 0;
    _formatWriteFeatures = 0;
    _formatWriteFeaturesToChange = 0;
}

默認情況下,Date類型序列化將調(diào)用DateSerializer的_timestamp 方法:

/**
 * For efficiency, we will serialize Dates as longs, instead of
 * potentially more readable Strings.
 */
@JacksonStdImpl
@SuppressWarnings("serial")
public class DateSerializer extends DateTimeSerializerBase<Date> {
    ...
    @Override
    protected long _timestamp(Date value) {
        return (value == null) ? 0L : value.getTime();
    }
    @Override
    public void serialize(Date value, JsonGenerator g, SerializerProvider provider) throws IOException {
        if (_asTimestamp(provider)) {
            g.writeNumber(_timestamp(value));
            return;
        }
        _serializeAsString(value, g, provider);
    }
}

DateTimeSerializerBase的_asTimestamp方法:

protected boolean _asTimestamp(SerializerProvider serializers)
{
    if (_useTimestamp != null) {
        return _useTimestamp.booleanValue();
    }
    if (_customFormat == null) {
        if (serializers != null) {
            return serializers.isEnabled(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
        }
        // 12-Jun-2014, tatu: Is it legal not to have provider? Was NPE:ing earlier so leave a check
        throw new IllegalArgumentException("Null SerializerProvider passed for "+handledType().getName());
    }
    return false;
}

禁用WRITE_DATES_AS_TIMESTAMPS

若要將日期序列化為字符串,可禁用SerializationFeature.WRITE_DATES_AS_TIMESTAMPS:

mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);

這時序列化將調(diào)用StdDateFormat的format()方法,使用ISO-8601兼容格式"yyyy-MM-dd'T'HH:mm:ss.SSSZ",輸出內(nèi)容如下:

{"name":"Jason","birthday":"2018-10-31T03:07:34.485+0000"}

StdDateFormat反序列化支持ISO-8601兼容格式和RFC-1123("EEE, dd MMM yyyy HH:mm:ss zzz")格式。

@JsonFormat

使用@JsonFormat注解,代替全局設(shè)置,是一種更靈活的方法:

@JsonFormat(shape = JsonFormat.Shape.STRING)
private Date birthday;

還可以定義pattern:

@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd")
private Date birthday;

當(dāng)自定義pattern后,將創(chuàng)建新的SimpleDateFormat實例來序列化日期,參見DateTimeSerializerBase的createContextual()方法:

public JsonSerializer<?> createContextual(SerializerProvider serializers, BeanProperty property) throws JsonMappingException
{
  ...
  if (format.hasPattern()) {
      final Locale loc = format.hasLocale() ? format.getLocale() : serializers.getLocale();
      SimpleDateFormat df = new SimpleDateFormat(format.getPattern(), loc);
      TimeZone tz = format.hasTimeZone() ? format.getTimeZone() : serializers.getTimeZone();
      df.setTimeZone(tz);
      return withFormat(Boolean.FALSE, df);
  }
  ...
}

Spring Boot與Jackson ObjectMapper

Spring Boot使用HttpMessageConverters處理HTTP交換中的內(nèi)容轉(zhuǎn)換。

當(dāng)classpath中存在Jackson時,Jackson2ObjectMapperBuilder將是默認的Converter,源碼請查看HttpMessageConverters和WebMvcConfigurationSupport:

HttpMessageConverters

private List<HttpMessageConverter<?>> getDefaultConverters() {
    List<HttpMessageConverter<?>> converters = new ArrayList<>();
    if (ClassUtils.isPresent("org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport", null)) {
        converters.addAll(new WebMvcConfigurationSupport() {
            public List<HttpMessageConverter<?>> defaultMessageConverters() {
                return super.getMessageConverters();
            }
        }.defaultMessageConverters());
    }
    else {
        converters.addAll(new RestTemplate().getMessageConverters());
    }
    reorderXmlConvertersToEnd(converters);
    return converters;
}

WebMvcConfigurationSupport

protected final void addDefaultHttpMessageConverters(List<HttpMessageConverter<?>> messageConverters) {
    StringHttpMessageConverter stringHttpMessageConverter = new StringHttpMessageConverter();
    stringHttpMessageConverter.setWriteAcceptCharset(false);  // see SPR-7316
    messageConverters.add(new ByteArrayHttpMessageConverter());
    messageConverters.add(stringHttpMessageConverter);
    messageConverters.add(new ResourceHttpMessageConverter());
    messageConverters.add(new ResourceRegionHttpMessageConverter());
    messageConverters.add(new SourceHttpMessageConverter<>());
    messageConverters.add(new AllEncompassingFormHttpMessageConverter());
    ...
    if (jackson2Present) {
        Jackson2ObjectMapperBuilder builder = Jackson2ObjectMapperBuilder.json();
        if (this.applicationContext != null) {
            builder.applicationContext(this.applicationContext);
        }
        messageConverters.add(new MappingJackson2HttpMessageConverter(builder.build()));
    }
    ...
}

默認,Jackson2ObjectMapperBuilder將創(chuàng)建ObjectMapper實例:

Jackson2ObjectMapperBuilder

public <T extends ObjectMapper> T build() {
    ObjectMapper mapper;
    if (this.createXmlMapper) {
        mapper = (this.defaultUseWrapper != null ?
                new XmlObjectMapperInitializer().create(this.defaultUseWrapper) :
                new XmlObjectMapperInitializer().create());
    }
    else {
        mapper = (this.factory != null ? new ObjectMapper(this.factory) : new ObjectMapper());
    }
    configure(mapper);
    return (T) mapper;
}

ObjectMapper以下屬性被禁用:

  • MapperFeature.DEFAULT_VIEW_INCLUSION
  • DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES
  • SerializationFeature.WRITE_DATES_AS_TIMESTAMPS

Jackson2ObjectMapperBuilder

private void customizeDefaultFeatures(ObjectMapper objectMapper) {
    if (!this.features.containsKey(MapperFeature.DEFAULT_VIEW_INCLUSION)) {
        configureFeature(objectMapper, MapperFeature.DEFAULT_VIEW_INCLUSION, false);
    }
    if (!this.features.containsKey(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)) {
        configureFeature(objectMapper, DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    }
}

JacksonAutoConfiguration

static {
    Map<Object, Boolean> featureDefaults = new HashMap<>();
    featureDefaults.put(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
    FEATURE_DEFAULTS = Collections.unmodifiableMap(featureDefaults);
}

自定義Jackson ObjectMapper配置

針對ObjectMapper的六種Feature,Spring Boot都提供了相應(yīng)的配置,列表如下:

Feature(Enum)Spring Boot PropertyValues
com.fasterxml.jackson.databind.DeserializationFeaturespring.jackson.deserialization.feature_nametrue, false
com.fasterxml.jackson.core.JsonGenerator.Featurespring.jackson.generator.feature_nametrue, false
com.fasterxml.jackson.databind.MapperFeaturespring.jackson.mapper.feature_nametrue, false
com.fasterxml.jackson.core.JsonParser.Featurespring.jackson.parser.feature_nametrue, false
com.fasterxml.jackson.databind.SerializationFeaturespring.jackson.serialization.feature_nametrue, false
com.fasterxml.jackson.annotation.JsonInclude.Includespring.jackson.default-property-inclusionalways, non_null, non_absent, non_default, non_empty

例如,為啟用美化打印,設(shè)置spring.jackson.serialization.indent_output=true,相當(dāng)于啟用SerializationFeature.INDENT_OUTPUT,配置中忽略feature_name大小寫。

其他的Jackson配置屬性:

  • spring.jackson.date-format= # Date format string or a fully-qualified date format class name. For instance, yyyy-MM-dd HH:mm:ss.
  • spring.jackson.joda-date-time-format= # Joda date time format string. If not configured, "date-format" is used as a fallback if it is configured with a format string.
  • spring.jackson.locale= # Locale used for formatting.
  • spring.jackson.property-naming-strategy= # One of the constants on Jackson's PropertyNamingStrategy. Can also be a fully-qualified class name of a PropertyNamingStrategy subclass.
  • spring.jackson.time-zone= # Time zone used when formatting dates. For instance, "America/Los_Angeles" or "GMT+10".

其中spring.jackson.date-format默認值為com.fasterxml.jackson.databind.util.StdDateFormat。

@DateTimeFormat和@JsonFormat

在REST編程中,當(dāng)提交application/json的POST/PUT請求時,JSON會通過Jackson進行轉(zhuǎn)換。

當(dāng)提交GET請求時,如參數(shù)中包含日期,后臺代碼需要使用注解@DateTimeFormat:

@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date startDate;

兩者可以同時使用:

@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd")
@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date startDate;

總結(jié)

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • SpringBoot啟動時運行特定代碼的多種方式小結(jié)

    SpringBoot啟動時運行特定代碼的多種方式小結(jié)

    SpringBoot提供了多種方式在應(yīng)用程序啟動時運行特定的代碼,包括CommandLineRunner、ApplicationRunner、@PostConstruct、InitializingBean、事件機制和自定義注解等,下面就來具體介紹一下
    2025-01-01
  • 簡單了解Java關(guān)鍵字throw和throws的區(qū)別

    簡單了解Java關(guān)鍵字throw和throws的區(qū)別

    這篇文章主要介紹了簡單了解Java關(guān)鍵字throw和throws的區(qū)別,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2019-11-11
  • Java持久層面試題目及答案整理

    Java持久層面試題目及答案整理

    在本篇文章里小編給大家分享的是一篇關(guān)于Java持久層面試題目及答案整理內(nèi)容,需要的朋友們學(xué)習(xí)參考下。
    2020-02-02
  • java中volatile關(guān)鍵字的作用與實例代碼

    java中volatile關(guān)鍵字的作用與實例代碼

    這篇文章主要給大家介紹了關(guān)于java中volatile關(guān)鍵字的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-04-04
  • 零基礎(chǔ)寫Java知乎爬蟲之將抓取的內(nèi)容存儲到本地

    零基礎(chǔ)寫Java知乎爬蟲之將抓取的內(nèi)容存儲到本地

    上一回我們說到了如何把知乎的某些內(nèi)容爬取出來,那么這一回我們就說說怎么把這些內(nèi)容存儲到本地吧。
    2014-11-11
  • Java基礎(chǔ) Servlet監(jiān)聽器詳解

    Java基礎(chǔ) Servlet監(jiān)聽器詳解

    這篇文章主要介紹了Java基礎(chǔ) Servlet監(jiān)聽器詳解的相關(guān)資料,需要的朋友可以參考下
    2017-07-07
  • SpringBoot整合OpenFeign的坑

    SpringBoot整合OpenFeign的坑

    最近試用SpringBoot+K8S,遇到了個坑,通過OpenFeign請求返回值LocalDateTime發(fā)生了異常,本文就詳細的介紹一下解決方法,感興趣的可以了解一下
    2021-07-07
  • Java將一個正整數(shù)分解質(zhì)因數(shù)的代碼

    Java將一個正整數(shù)分解質(zhì)因數(shù)的代碼

    這篇文章主要介紹了將一個正整數(shù)分解質(zhì)因數(shù)。例如:輸入90,打印出90=2*3*3*5,需要的朋友可以參考下
    2017-02-02
  • SpringCloud微服務(wù) Sentinel 實戰(zhàn)指南

    SpringCloud微服務(wù) Sentinel 實戰(zhàn)指南

    文章主要介紹了Sentletinel在微服務(wù)中的應(yīng)用及工作原理,涵蓋了流控規(guī)則、熔斷降級、授權(quán)控制等內(nèi)容,強調(diào)了通過合理的限流和降級策略來保護系統(tǒng)穩(wěn)定運行,感興趣的朋友跟隨小編一起看看吧
    2026-05-05
  • Java中避免寫嵌套if樣式的代碼詳解

    Java中避免寫嵌套if樣式的代碼詳解

    這篇文章主要給大家介紹了在Java中如何避免寫嵌套if樣式的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家具有一定的參考學(xué)習(xí)價值,需要的朋友們下面跟著小編一起來學(xué)習(xí)學(xué)習(xí)吧。
    2017-07-07

最新評論

宜阳县| 周宁县| 巧家县| 汪清县| 永康市| 蒲城县| 泸州市| 吉林市| 合川市| 阳西县| 乌审旗| 惠来县| 河东区| 丹江口市| 胶南市| 盐城市| 元谋县| 广元市| 黄骅市| 洪湖市| 昌江| 乌兰浩特市| 娄底市| 白朗县| 新巴尔虎左旗| 揭西县| 蕉岭县| 永定县| 天全县| 陆丰市| 长沙县| 邹城市| 建水县| 革吉县| 长宁县| 张家界市| 株洲县| 六安市| 大洼县| 泽州县| 秦安县|