Springboot2以代码的方式统一配置Jackson教程

目录
  • 说明
  • 7个序列化和反序列化规则
  • Jackson统一配置类
  • Jackson工具类
  • 总结

说明

本文主要配置Jackson对Long、Date、LocalDate、LocalDateTime的序列化和反序列化。

由于js中整数可精确表示范围小于java Long的范围,故将Long序列化为String,反序列化Jackson会自动处理String转Long,故不需要显式配置。

由于时间戳在各语言间的兼容性良好,故将Date、LocalDate、LocalDateTime序列化为Long(目前时间戳类的Long类型在js的可精确表示范围内),将Long反序列化为Date、LocalDate、LocalDateTime。将String空字符串反序列化为null。

本文除了配置Springboot整合的Jackson,还配置了功能一致的Jackson工具类,方便在代码中显示使用Jackson的序列化和反序列化功能。

7个序列化和反序列化规则

package com.xxx.config.serializers;
import java.io.IOException;
import java.util.Date;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
public class DateSerializer extends JsonSerializer<Date> {
 @Override
 public void serialize(Date value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
  if (value != null) {
   gen.writeNumber(value.getTime());
  }
 }
}
package com.xxx.config.serializers;
import java.io.IOException;
import java.time.LocalDate;
import java.time.ZoneId;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
public class LocalDateSerializer extends JsonSerializer<LocalDate> {
 @Override
 public void serialize(LocalDate value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
  if (value != null) {
   long millis = value.atStartOfDay(ZoneId.of("+8")).toInstant().toEpochMilli();
   gen.writeNumber(millis);
  }
  }
   }
package com.xxx.config.serializers;
import java.io.IOException;
import java.time.LocalDateTime;
import java.time.ZoneId;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
public class LocalDateTimeSerializer extends JsonSerializer<LocalDateTime> {
 @Override
 public void serialize(LocalDateTime value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
  if (value != null) {
   long millis = value.atZone(ZoneId.of("+8")).toInstant().toEpochMilli();
   gen.writeNumber(millis);
  }
 }
}
package com.xxx.config.serializers;
import java.io.IOException;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
public class StringDeserializer extends JsonDeserializer<String> {
 @Override
 public String deserialize(JsonParser p, DeserializationContext ctxt)
   throws IOException, JsonProcessingException {
  String text = p.getText();
  if ("".equals(text)) {
   return null;
  }
  return text;
 }
}
package com.xxx.config.serializers;
import java.io.IOException;
import java.util.Date;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
public class DateDeserializer extends JsonDeserializer<Date> {
 @Override
 public Date deserialize(JsonParser p, DeserializationContext ctxt)
   throws IOException, JsonProcessingException {
  long timestamp = p.getValueAsLong();
        if (timestamp > 0){
            return new Date(timestamp);
        }else{
            return null;
        }
 }
}
package com.xxx.config.serializers;
import java.io.IOException;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
public class LocalDateDeserializer extends JsonDeserializer<LocalDate> {
 @Override
 public LocalDate deserialize(JsonParser p, DeserializationContext ctxt)
   throws IOException, JsonProcessingException {
  long timestamp = p.getValueAsLong();
        if (timestamp > 0){
            return LocalDateTime.ofInstant(Instant.ofEpochMilli(timestamp),ZoneId.of("+8")).toLocalDate();
        }else{
            return null;
        }
 }
}
package com.xxx.config.serializers;
import java.io.IOException;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
public class LocalDateTimeDeserializer extends JsonDeserializer<LocalDateTime> {
 @Override
 public LocalDateTime deserialize(JsonParser p, DeserializationContext ctxt)
   throws IOException, JsonProcessingException {
  long timestamp = p.getValueAsLong();
        if (timestamp > 0){
            return LocalDateTime.ofInstant(Instant.ofEpochMilli(timestamp),ZoneId.of("+8"));
        }else{
            return null;
        }
 }
}

Jackson统一配置类

package com.xxx.config;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Date;
import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
import com.xxx.config.serializers.DateDeserializer;
import com.xxx.config.serializers.DateSerializer;
import com.xxx.config.serializers.LocalDateDeserializer;
import com.xxx.config.serializers.LocalDateSerializer;
import com.xxx.config.serializers.LocalDateTimeDeserializer;
import com.xxx.config.serializers.LocalDateTimeSerializer;
import com.xxx.config.serializers.StringDeserializer;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
@Configuration
public class JacksonConfig {
 @Bean
 public Jackson2ObjectMapperBuilderCustomizer jackson2ObjectMapperBuilderCustomizer() {
  Jackson2ObjectMapperBuilderCustomizer customizer = new Jackson2ObjectMapperBuilderCustomizer() {

   @Override
   public void customize(Jackson2ObjectMapperBuilder jacksonObjectMapperBuilder) {
    jacksonObjectMapperBuilder
      .serializerByType(Long.TYPE, ToStringSerializer.instance)
      .serializerByType(Long.class, ToStringSerializer.instance)
      .serializerByType(Date.class, new DateSerializer())
      .serializerByType(LocalDate.class, new LocalDateSerializer())
      .serializerByType(LocalDateTime.class, new LocalDateTimeSerializer())
      .deserializerByType(String.class, new StringDeserializer())
      .deserializerByType(Date.class, new DateDeserializer())
      .deserializerByType(LocalDate.class, new LocalDateDeserializer())
      .deserializerByType(LocalDateTime.class, new LocalDateTimeDeserializer())
      .failOnEmptyBeans(false)
      .failOnUnknownProperties(false);
   }
  };
  return customizer;
 }
}

Jackson工具类

package com.xxx.util;
import java.io.IOException;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.TimeZone;
import com.xxx.config.serializers.StringDeserializer;
import com.xxx.config.serializers.DateDeserializer;
import com.xxx.config.serializers.DateSerializer;
import com.xxx.config.serializers.LocalDateDeserializer;
import com.xxx.config.serializers.LocalDateSerializer;
import com.xxx.config.serializers.LocalDateTimeDeserializer;
import com.xxx.config.serializers.LocalDateTimeSerializer;
import com.fasterxml.jackson.core.JsonParser.Feature;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
public class JsonUtils {

 private static final ObjectMapper objectMapper;
 static {
  objectMapper = new ObjectMapper();
  // 去掉默认的时间戳格式
  objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
  // 设置为中国北京时区
  objectMapper.setTimeZone(TimeZone.getTimeZone("GMT+8"));
  // 空值不序列化
//  objectMapper.setSerializationInclusion(Include.NON_NULL);//已过时
//  objectMapper.setDefaultPropertyInclusion(Include.NON_NULL);//新API
  // 反序列化时,属性不存在的兼容处理
  objectMapper.getDeserializationConfig().withoutFeatures(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
  objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
  objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
  // 单引号处理
  objectMapper.configure(Feature.ALLOW_SINGLE_QUOTES, true);

  JavaTimeModule javaTimeModule = new JavaTimeModule();
  javaTimeModule.addSerializer(Long.TYPE, ToStringSerializer.instance);
  javaTimeModule.addSerializer(Long.class, ToStringSerializer.instance);
  javaTimeModule.addSerializer(Date.class, new DateSerializer());
  javaTimeModule.addSerializer(LocalDate.class, new LocalDateSerializer());
        javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer());
        javaTimeModule.addDeserializer(String.class, new StringDeserializer());
        javaTimeModule.addDeserializer(Date.class, new DateDeserializer());
        javaTimeModule.addDeserializer(LocalDate.class, new LocalDateDeserializer());
        javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer());
        objectMapper.registerModule(javaTimeModule);
 }

 /**
  * json 转换成 Object
  *
  * @param json
  * @param clazz
  * @return
  */
 public static <T> T json2Object(String json, Class<T> clazz) {
  try {
   return objectMapper.readValue(json, clazz);
  } catch (IOException e) {
   throw new RuntimeException("解析json错误");
  }
 }

 @SuppressWarnings("unchecked")
 public static <T> T json2Object(String json, TypeReference<T> tr) {
  try {
   return (T)objectMapper.readValue(json, tr);
  } catch (IOException e) {
   throw new RuntimeException("解析json错误", e);
  }
 }

 /**
  * obj 转换成json
  *
  * @param entity
  * @return
  */
 public static <T> String object2Json(T entity) {
  try {
   return objectMapper.writeValueAsString(entity);
  } catch (IOException e) {
   throw new RuntimeException("转换json错误");
  }
 }

 /**
  * obj对象 转换成树型JSON
  *
  * @param obj
  * @return
  */
 public static JsonNode object2TreeJson(Object obj) {
  try {
   return objectMapper.valueToTree(obj);
  } catch (Exception e) {
   throw new RuntimeException("转换json错误");
  }
 }

   /**
     * 解码json串成对象
     *
     * @param <T>
     * @param json
     * @param valueType
     * @return T
     */
    @SuppressWarnings("unchecked")
    public static <T> T decode(String json, Class<?> valueType) {
        try {
            return (T) objectMapper.readValue(json, valueType);
        } catch (Exception e) {
            throw new RuntimeException(json, e);
        }
    }
 /**
     * 解码json串成JsonNode
     * @param json
     * @return
     */
    public static JsonNode readTree(String json) {
     try {
   return objectMapper.readTree(json);
  } catch (Exception e) {
   throw new RuntimeException(json, e);
  }
    }
}

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • springboot配置Jackson返回统一默认值的实现示例

    在项目开发中,我们返回的数据或者对象没有的时候一般直接返回的null 有数据时的返回值 { "flag": true, "code": "10000", "msg": "成功!", "data": { "id": 32, "templateType": 1, "templateName": "我的测试模板1"

  • SpringBoot2.0整合jackson配置日期格式化和反序列化的实现

    网上杂七杂八的说法不一,大多数都是抄来抄去,没有实践,近期在项目频繁遇到boot+jackson处理日期的问题,故开此贴. 首先是POM <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance

  • 详解springboot之jackson的两种配置方式

    springboot 针对jackson是自动化配置的,如果需要修改,有两种方式: 方式一:通过application.yml 配置属性说明:## spring.jackson.date-format指定日期格式,比如yyyy-MM-dd HH:mm:ss,或者具体的格式化类的全限定名 spring.jackson.deserialization是否开启Jackson的反序列化 spring.jackson.generator是否开启json的generators. spring.jackson

  • springboot jackson配置教程

    目录 springboot jackson配置 需求 全局配置 额外 测试 springboot配置jackSon处理字段 javaBean序列化为json jackson处理相关自动 springboot jackson配置 项目中使用的json是jackson.这个呢是spring boot自带的,一开始是用阿里的fastjson的.但是 总是有漏洞.还是用jackson,谷歌的gson也感觉非常棒. 需求 在controller 使用@RestController 返回json.使用的是

  • Springboot2以代码的方式统一配置Jackson教程

    目录 说明 7个序列化和反序列化规则 Jackson统一配置类 Jackson工具类 总结 说明 本文主要配置Jackson对Long.Date.LocalDate.LocalDateTime的序列化和反序列化. 由于js中整数可精确表示范围小于java Long的范围,故将Long序列化为String,反序列化Jackson会自动处理String转Long,故不需要显式配置. 由于时间戳在各语言间的兼容性良好,故将Date.LocalDate.LocalDateTime序列化为Long(目前时

  • SpringBoot如何统一配置bean的别名

    这篇文章主要介绍了SpringBoot如何统一配置bean的别名,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 所谓别名, 就是在mappper.xml配置文件中像什么resultType="xxx" 不需要写全限定类名, 只需要写类名即可. 配置方式有两种: 1. 在 application.yml中 #mybatis相关配置 mybatis: type-aliases-package: com.zzuli.domain 2. 在a

  • JS代码简洁方式之函数方法详解

    函数的参数越少越好 有一个准则是:如果你的函数参数超过两个,就应该改为对象传入. 这样做是合理的,因为当函数参数超过两个时,参数顺序开始变得难以记忆,而且容易出现一种很尴尬的情况:比如我只需要传入第三个参数,因为其自身顺序的原因,不得不补齐前两个根本用不上的参数,以让它顺利排在第三位. // bad const createArticle = (title, author, date, content) => { } createArticle('震惊,一男子竟偷偷干这事', 'zhangnan

  • 使用Spring开启@Async异步方式(javaconfig配置)

    目录 Spring开启@Async异步(javaconfig配置) 应用场景 创建AsyncTask 创建spring配置AppConfig 测试 Spring @Async Demo Spring开启@Async异步(javaconfig配置) 在Spring中,基于@Async标注的方法,称之为异步方法:这些方法将在执行的时候,将会在独立的线程中被执行,调用者无需等待它的完成,即可继续其他的操作. 应用场景 某些耗时较长的而用户不需要等待该方法的处理结果 某些耗时较长的方法,后面的程序不需要

  • SpringBoot2零基础到精通之自动配置底层分析及小技巧

    目录 1 自动配置底层分析 1.1 ​自动配置注解解析 1.2 修改默认配置 1.3 总结 1.4 最佳实践 2 开发小技巧 2.1 Lombok简化开发 2.2 伪热更新 2.3 创建Spring Initailizr项目 1 自动配置底层分析 1.1 ​自动配置注解解析 @SpringBootApplication注解是SpringBoot的核心注解,他是由以下三个注解总和而成. @SpringBootConfiguration 该注解底层有一个@Configuration注解,标明当前类是

  • SpringCloud Config统一配置中心问题分析解决与客户端动态刷新实现

    目录 一.问题分析及解决方案 1.问题分析 2.解决方案 二.手动刷新 1.添加服务监控 2.暴露服务端点 3.刷新业务类controller 4.手动刷新 三.自动刷新 什么是总线 基本原理 一.问题分析及解决方案 1.问题分析 上一章我们讲过远程仓储统一管理配置信息,客户端可以通过统一配置服务中心 config server 服务端获取配置信息.现在我们来做一个改变,并进行分析. 首先启动注册中心.统一配置中心configserver服务端.订单服务.浏览器访问地址:http://local

  • 详解Android使用Gradle统一配置依赖管理

    在介绍使用 Gradle 统一配置依赖管理前我们先来简单介绍一下 Gradle, Gradle 是一个基于 JVM 的构建工具,也是一款非常灵活强大的构建工具,支持  jcenter.maven.Ivy 仓库,支持传递性依赖管理(即 A 依赖 B,B 依赖 C,那么 A 也就可以依赖 C,不用再单独去依赖),而不需要远程仓库或者是 pom.xml 和 ivy.xml 配置文件,抛弃了各种繁琐,基于 Groovy,build 脚本使用 Groovy 编写 而在我们的 Android studio

  • c++代码调试方式的几点建议

    1.代码调试的重要性 代码调试在程序开发阶段占有举足轻重的地位,可见代码调试的重要性.但是有一点必须强调:程序是设计出来的,而不是调试出来的.这是所有程序员必须牢记在心的一条准则.一个没有设计或者这几得很糟糕的程序,无论怎样调试,也不会成为一个合格的程序. 程序有着良好的设计的前提下,软件开发的过程中,编码错误在所难免.所有程序可能出现的错误可分为两类:语法错误和逻辑错误.调试通常是指在消除了语法错误之后,发现程序中的逻辑错误的过程.对C/C++程序进行调试,有这样集中常用的手段.它们既可以单独

  • SpringBoot2.4.2下使用Redis配置Lettuce的示例

    目录 1. Springboot2.4.2下对Redis的基础集成 1.1 maven添加依赖 1.2 添加Redis配置文件 1.3 注册RedisTemplate和StringRedisTemplate的Bean 1.4 编写一个控制器示例进行redis操作 2. 使用redis进行发布订阅 2.1 添加一个发布者的接口 2.2 添加一个发布者的实现类 2.3 添加一个消息监听bean 2.4 添加bean注册 2.5 改写之前的控制器如下 3. 监听key的过期事件 1. Springbo

随机推荐