关闭
Hit
enter
to search or
ESC
to close
May I Suggest ?
#leanote #leanote blog #code #hello world
Okeeper's Blog
Home
Archives
Tags
DevOps
软件笔记
Spring
学习
JVM系列
关于我
Spring boot 配置自定义Json类型转换
无
3924
0
0
zhangyue
## 项目中遇到一个问题,就是由于我们数据库表ID使用分布式唯一算法生成的Long类型,所以有很长(19位数字),导致转成json传至前端js使用时报错,因为js的数字类型最大只能表示15个数字长度,见[Javascript 的number对象说明](http://www.w3school.com.cn/js/js_obj_number.asp) ## 解决方案:使用Spring自定义的Json序列化,将过长的Long类型转成String类型给到js使用,这样就不会有问题了 **中途遇到了许多坑,在这里记录一下** # 局部配置某个字段的序列化 1. 实现抽象接口`JsonSerializer`自定义序列化类 ``` public class MyLongConverter extends JsonSerializer<Long> { @Override public void serialize(Long value, JsonGenerator gen, SerializerProvider serializers) throws IOException, JsonProcessingException { if (value.toString().length() > 12) { gen.writeString(value.toString()); log.info("the Long value is to long. will convert to String"); } else { gen.writeNumber(value); } } } ``` 2. 使用`@JsonSerialize(using = CustomLongConverter.class)`注解到指定字段上 ``` @JsonSerialize(using = CustomLongConverter.class) private Long storageId; ``` # 全局配置序注册自定义的序列化类 ## 使用在`@Configration`类中使用`@Bean`配置 1. 定义一个继承制StdSerializer类的一个自定义序列化 ``` public class CustomLongConverter extends StdSerializer<Long> { public CustomLongConverter() { super(Long.class); } @Override public void serialize(Long value, JsonGenerator gen, SerializerProvider serializers) throws IOException, JsonProcessingException { if (value.toString().length() > 12) { gen.writeString(value.toString()); log.info("the Long value is to long. will convert to String"); } else { gen.writeNumber(value); } } } ``` 2. 注册到ObjectMapper中 - 参考官方文档[ Customize the Jackson ObjectMapper](https://docs.spring.io/spring-boot/docs/current/reference/html/howto-spring-mvc.html#howto-customize-the-jackson-objectmapper) - 参考文章[How to customise the Jackson JSON mapper implicitly used by Spring Boot? ](https://stackoverflow.com/questions/28324352/how-to-customise-the-jackson-json-mapper-implicitly-used-by-spring-boot) - 参考[自定义Jackson ObjectMapper把Long型转化为String类型](http://blog.csdn.net/L_Sail/article/details/70217393) - 参考[Java Web程序中利用Spring框架返回JSON格式的日期](http://www.jb51.net/article/85093.htm) Spring boot 默认使用`Jackson2ObjectMapperBuilder` 来构建ObjectMapper,如果想添加一些自定义的序列化只需定义`Jackson2ObjectMapperBuilderCustomizer`的Bean就可以将自定义的序列化注册到全局的ObjectMapper中, 在`@Configration`配置类中加入 ``` @Bean public Jackson2ObjectMapperBuilderCustomizer initJackson() { Jackson2ObjectMapperBuilderCustomizer c = new Jackson2ObjectMapperBuilderCustomizer() { @Override public void customize(Jackson2ObjectMapperBuilder builder) { //自定义Long类型转换 超过12个数字用String格式返回,由于js的number只能表示15个数字 builder.serializerByType(Long.class,new CustomLongConverter()); builder.serializerByType(Long.TYPE,new CustomLongConverter()); builder.serializationInclusion(JsonInclude.Include.NON_NULL);//不包含为空的字段 builder.serializationInclusion(JsonInclude.Include.NON_EMPTY);//不包含空字符串字段 builder.indentOutput(true).dateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")); } }; return c; } ``` 如果只是想在Mvc中的@ResponBody中生效,则可以用以下配置 ``` public class Bootstrap extends WebMvcConfigurerAdapter { public static void main(String[] args) { SpringApplication.run(Bootstrap.class, args); log.info("application start success!"); } @Override public void configureMessageConverters(List<HttpMessageConverter<?>> converters) { Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder(); builder.serializationInclusion(JsonInclude.Include.NON_NULL); //builder.serializationInclusion(JsonInclude.Include.NON_EMPTY); builder.indentOutput(true).dateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")); //自定义Long类型转换 超过12个数字用String格式返回,由于js的number只能表示15个数字 builder.serializerByType(Long.class,new CustomLongConverter()); builder.serializerByType(Long.TYPE,new CustomLongConverter()); converters.add(0,new MappingJackson2HttpMessageConverter(builder.build())); } } ``` 如果想完全替换ObjectMapper序列化器,可以自定义`Jackson2ObjectMapperBuilder` 的Bean并且将Bean的优先级设置为`@Primary`,但是我们这里不需要,只需要注册上自定义的序列化就可以了 ## xml的配置注册方式 1. 在spring上下文中加入一下配置 ``` <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.1.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.1.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd"> <mvc:annotation-driven> <mvc:message-converters register-defaults="false"> <bean id="converter" class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"> <property name="objectMapper"> <bean class="org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean"> <property name="serializers"> <array> <!--自定义的类型转换--> <bean class="com.baibei.portal.center.util.CustomLongConverter"/> </array> </property> <property name="dateFormat"> <bean class="java.text.SimpleDateFormat"> <constructor-arg type="java.lang.String" value="yyyy-MM-dd HH:mm:ss"/> </bean> </property> </bean> </property> </bean> </mvc:message-converters> </mvc:annotation-driven> </beans> ``` > 注意:,这一有一个坑,当xml的上下文中有多余的 `<mvc:annotation-driven>`,它将生成默认生成一个优先级较高的相关配置interceptor,http message converter,所以如果使用xml配置,要将其包含在`<mvc:annotation-driven ></mvc:annotation-driven>`并且将其他多余的`<mvc:annotation-driven>`去掉,否则这些配置将被覆盖失效
觉得不错,点个赞?
Please enable JavaScript to view the
comments powered by Disqus.
comments powered by
Disqus
文章目录