来源 :https://my.oschina.net/Adven/blog/3036567

使用springboot-web编写rest接口,接口需要返回json数据,目前国内比较常用的fastjson使用比较方便,但是SpringBoot默认使用的Jackson,替换的时候有时候因为其他组件也使用到了jackson,所以无法100%成功替换。 不喜欢使用jackson主要是jackson对格式化输出支持不太友好,自己使用的时候遇到许多坑,至今也没把坑填好,所以一直就不待见它,有时候又不得不用。 下面总结一下Fastjson/Jackson两种对json序列化+格式化输出的配置总结。

1.Jackson方式(SpringBoot中的默认方式):

1.1application.yml配置文件

spring:
jackson:
#日期格式化
date-format: yyyy-MM-dd HH:mm:ss
serialization:
#格式化输出
indent_output: true
  • 网上提供的方案,可是实际配置并不能生效

1.2使用JavaConfig文件配置Jackson格式化输出

@Configuration
public class JacksonConfig extends WebMvcConfigurationSupport { /**
* 格式化输出配置
* @param converters
*/
@Override
protected void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
for (HttpMessageConverter<?> converter : converters) {
if (converter instanceof MappingJackson2HttpMessageConverter) {
MappingJackson2HttpMessageConverter jacksonConverter = (MappingJackson2HttpMessageConverter) converter;
jacksonConverter.setPrettyPrint( true ); // 实际使用生效
}
}
}
}

2.Fastjson方式

2.1引入fastjson,排除jackson

<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.56</version>
</dependency> <!--排除jackson-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</exclusion>
</exclusions>
</dependency>
<!--,排除jackson(根据实际情况,下面的非必须)-->
<dependency>
<groupId>org.springframework.security.oauth</groupId>
<artifactId>spring-security-oauth2</artifactId>
<version>2.3.4.RELEASE</version>
<!--<exclusions>-->
<!--<exclusion>-->
<!--<groupId>com.fasterxml.jackson.core</groupId>-->
<!--<artifactId>jackson-databind</artifactId>-->
<!--</exclusion>-->
<!--</exclusions>-->
</dependency>
<dependency>
<groupId>org.springframework.security.oauth.boot</groupId>
<artifactId>spring-security-oauth2-autoconfigure</artifactId>
<version>${spring-boot.version}</version>
<scope>compile</scope>
<!--<exclusions>-->
<!--<exclusion>-->
<!--<groupId>com.fasterxml.jackson.core</groupId>-->
<!--<artifactId>jackson-databind</artifactId>-->
<!--</exclusion>-->
<!--</exclusions>-->
</dependency>

2.2 使用JavaConfig配置

  • SpringBoot中fastjson的配置有两种方式:

2.2.1 方式一

配置Bean 使用fastjson的方式实现HttpMessageConverters

@Configuration
public class FastJSONConfig {
/**
* Fastjson
*
* @return
*/
@Bean
public HttpMessageConverters fastJsonHttpMessageConverters() {
FastJsonHttpMessageConverter fastJsonHttpMessageConverter = new FastJsonHttpMessageConverter();
FastJsonConfig fastJsonConfig = new FastJsonConfig();
List<MediaType> mediaTypes = new ArrayList<>();
mediaTypes.add(MediaType.APPLICATION_JSON_UTF8);
fastJsonHttpMessageConverter.setSupportedMediaTypes(mediaTypes);
fastJsonConfig.setSerializerFeatures(
SerializerFeature.DisableCircularReferenceDetect, //禁用循环引用
SerializerFeature.PrettyFormat,
SerializerFeature.IgnoreNonFieldGetter
);
fastJsonHttpMessageConverter.setFastJsonConfig(fastJsonConfig);
HttpMessageConverter<?> converter = fastJsonHttpMessageConverter;
return new HttpMessageConverters(converter);
}
}

2.2.2方式二

  • Spring5.x中实现WebMvcConfigurer接口,并重写configureMessageConverters方法,向其中添加FastJsonHttpMessageConverter
@Configuration
public class FastJsonHttpConverterConfig implements WebMvcConfigurer {
// fastjson配置
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
Iterator<HttpMessageConverter<?>> iterator = converters.iterator();
while(iterator.hasNext()){
HttpMessageConverter<?> converter = iterator.next();
if(converter instanceof MappingJackson2HttpMessageConverter){
iterator.remove();
}
}
FastJsonHttpMessageConverter converter = new FastJsonHttpMessageConverter();
FastJsonConfig config = new FastJsonConfig();
config.setSerializerFeatures(SerializerFeature.WriteNullListAsEmpty, // List类型字段为null时输出[]而非null
SerializerFeature.WriteMapNullValue, // 显示空字段
SerializerFeature.WriteNullStringAsEmpty, // 字符串类型字段为null时间输出""而非null
SerializerFeature.WriteNullBooleanAsFalse, // Boolean类型字段为null时输出false而null
SerializerFeature.PrettyFormat, // 美化json输出,否则会作为整行输出
SerializerFeature.WriteNullNumberAsZero, // 数值字段如果为null,输出为0,而非null
SerializerFeature.WriteNullBooleanAsFalse, // Boolean字段如果为null,输出为false,而非null
SerializerFeature.WriteDateUseDateFormat, // 时间格式yyyy-MM-dd HH: mm: ss
SerializerFeature.DisableCircularReferenceDetect); // 禁用循环引用检测
converter.setFastJsonConfig(config);
converters.add(converter);
List<MediaType> supportedMediaTypes = new ArrayList<>();
supportedMediaTypes.add(MediaType.APPLICATION_JSON);
supportedMediaTypes.add(MediaType.APPLICATION_JSON_UTF8);
supportedMediaTypes.add(MediaType.APPLICATION_ATOM_XML);
supportedMediaTypes.add(MediaType.APPLICATION_FORM_URLENCODED);
supportedMediaTypes.add(MediaType.APPLICATION_OCTET_STREAM);
supportedMediaTypes.add(MediaType.APPLICATION_PDF);
supportedMediaTypes.add(MediaType.APPLICATION_RSS_XML);
supportedMediaTypes.add(MediaType.APPLICATION_XHTML_XML);
supportedMediaTypes.add(MediaType.APPLICATION_XML);
supportedMediaTypes.add(MediaType.IMAGE_GIF);
supportedMediaTypes.add(MediaType.IMAGE_JPEG);
supportedMediaTypes.add(MediaType.IMAGE_PNG);
supportedMediaTypes.add(MediaType.TEXT_EVENT_STREAM);
supportedMediaTypes.add(MediaType.TEXT_HTML);
supportedMediaTypes.add(MediaType.TEXT_MARKDOWN);
supportedMediaTypes.add(MediaType.TEXT_PLAIN);
supportedMediaTypes.add(MediaType.TEXT_XML);
converter.setSupportedMediaTypes(supportedMediaTypes);
}
}

2.2.3 总结

  • fastjson替换jackson并不能保证100%成功,但是都能最终实现格式化输出。HttpMessageConverter的具体实现需要深入阅读源码,从源码上进一步寻找答案。
  • 使用fastjson替换在自己DIY的OAuth2-SSO项目中认证服务器无法成功替换,最后基于1中jackson最终实现格式化输出。

3.附Restful接口输出json数据

@RestController
public class UserController {
private static final Logger logger = LoggerFactory.getLogger(UserController.class); /**
* 资源服务器提供的受保护接口
* @param authentication
* @return
*/
@GetMapping(value = "/user",produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
public Authentication getUserInfo(Authentication authentication) {
logger.info("authentication resource: user {}", authentication);
System.out.println(JSON.toJSONString(authentication, SerializerFeature.PrettyFormat));
return authentication;
} /**
* 提供一个/user/me接口供客户端来获得用户的凭证
* @param principal
* @return
*/
@GetMapping(value = "/user/me",produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
public Principal getUserPrincipal(Principal principal) {
System.out.println("com.acanx.sso.oauthserver.controller.UserController#user Principal:"+principal);
logger.info("Principal: user {}", principal);
System.out.println(JSON.toJSONString(principal, SerializerFeature.PrettyFormat));
return principal;
}
}

SpringBoot中使用Fastjson/Jackson对JSON序列化格式化输出的若干问题的更多相关文章

  1. Java下用Jackson进行JSON序列化和反序列化(转)

    Java下常见的Json类库有Gson.JSON-lib和Jackson等,Jackson相对来说比较高效,在项目中主要使用Jackson进行JSON和Java对象转换,下面给出一些Jackson的J ...

  2. Json序列化指定输出字段 忽略属性

    DataContract 服务契约定义了远程访问对象和可供调用的方法,数据契约则是服务端和客户端之间要传送的自定义数据类型. 一旦声明一个类型为DataContract,那么该类型就可以被序列化在服务 ...

  3. python json.dumps()函数输出json格式,使用indent参数对json数据格式化输出

    在python中,要输出json格式,需要对json数据进行编码,要用到函数:json.dumps json.dumps() :是对数据进行编码 #coding=gbkimport json dict ...

  4. python中列表和元组的操作(结尾格式化输出小福利)

    一. 列表 1. 查 names = "YanFeixu WuYifan" names_1 = ["YanFeixu"," WuYifan" ...

  5. 用Jackson进行Json序列化时的常用注解

    Jackson时spring boot默认使用的json格式化的包,它的几个常用注解: @JsonIgnore 用在属性上面,在序列化和反序列化时都自动忽略掉该属性 @JsonProperty(&qu ...

  6. 关于spring中请求返回值的json序列化/反序列化问题

    https://cloud.tencent.com/developer/article/1381083 https://www.jianshu.com/p/db07543ffe0a 先留个坑

  7. 在JAVA中把JSON数据格式化输出到控制台

    public class ForMatJSONStr { public static void main(String[] args) { String jsonStr = "{\" ...

  8. JSON.stringify() 格式化 输出log

    调试程序的过程中,我们打印一个日志: console.log(object);,其中object是任意的一个json对象. 在控制台就会看到[object object],而看不到具体的内容. 我们可 ...

  9. springboot中json转换LocalDateTime失败的bug解决过程

    环境:jdk1.8.maven.springboot 问题:前端通过json传了一个日期:date:2019-03-01(我限制不了前端开发给到后端的日期为固定格式,有些人就是这么不配合),      ...

随机推荐

  1. B. Food Buying Round #617(递归 + 模拟)

    B. Food Buying time limit per test 1 second memory limit per test 256 megabytes input standard input ...

  2. Sqli-labs Less-58 报错注入 5次机会

    执行sql语句后,并没有返回数据库当中的数据,所以我们这里不能使用union联合注入,这里使用报错注入.但是需要注意这里只有5次机会尝试. 找表名 http://127.0.0.1/sql/Less- ...

  3. 整数回文数判断 Python

    判断一个整数是否是回文数.回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数. 输入:123  输出:false 输入:-121 输出:false 输入:121  输出:true 输入:1  ...

  4. Nginx 是如何处理 HTTP 头部的?

    Nginx 处理 HTTP 头部的过程 Nginx 在处理 HTTP 请求之前,首先需要 Nginx 的框架先和客户端建立好连接,然后接收用户发来的 HTTP 的请求行,比如方法.URL 等,然后接收 ...

  5. MTK Android 回调机制[CallBack]

    具体步骤: 一.建模 回调函数的关键是:将一段代码作为参数传递,而这段代码将会在某个时刻被执行 我理解的接口回调就是,我这个类实现了一个接口里的方法doSomething,然后注册到你这里,然后我就去 ...

  6. PHP中debug基本方法

    一.检查是否有语法错误 php -l test.php 二.基本调试基本调试 API: var_dump($var);print_r($var);echo $var; 基本的配置: display_e ...

  7. SQL基础系列(4)-性能优化建议

    10.1 连接查询表的顺序问题 SQLSERVER的解析器按照从右到左的顺序处理FROM子句中的表名,因此FROM子句中写在最后的表(基础表driving table)将被最先处理,在FROM子句中包 ...

  8. 《深入理解 Java 虚拟机》读书笔记:垃圾收集器与内存分配策略

    正文 垃圾收集器关注的是 Java 堆和方法区,因为这部分内存的分配和回收是动态的.只有在程序处于运行期间时才能知道会创建哪些对象,也才能知道需要多少内存. 虚拟机栈和本地方法栈则不需要过多考虑回收的 ...

  9. 智能指针 shared_ptr

    1.不支持数组 2.c++11支持make_shared,分配一次内存,构造函数为private和proteced时不能调用. 3.new初始化分配两次内存,一.分配数据块内存,二.分配控制块内存

  10. vuepress+gitee 构建在线项目文档

    目录 快速入门 在现有vue项目中安装本地开发依赖vuepress 在现有vue项目根目录下创建docs目录 创建并配置文档首页内容 运行,查看效果 可能会出现vue和vue-server-rende ...