SpringBoot返回json数据是很常见的需求,我们可以通过配置来控制实体对象的输出形式
目录
- 默认返回
- 通过配置格式化
- 通过注解实现属性设置
- 全局配置
- 参考
版本依赖
<parent>
<groupId></groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.7</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
通过一个简单的SpringBoot项目测试json数据返回格式
对象实体
package com.example.demo.dto;
import lombok.Data;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.Date;
@Data
public class User {
private String name;
private Integer age;
private String password;
private Date birthday;
private LocalDateTime localDateTime;
private LocalDate localDate;
private LocalTime localTime;
private LocalDateTime localDateTimeFormat;
}
控制器
package com.example.demo.controller;
import com.example.demo.dto.User;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.Date;
@RestController
public class UserController {
@GetMapping("/user")
@ResponseBody
public User getUser(){
User user = new User();
user.setAge(20);
user.setName("tom");
user.setPassword("123456");
user.setBirthday(new Date());
user.setLocalDateTime(LocalDateTime.now());
user.setLocalDate(LocalDate.now());
user.setLocalTime(LocalTime.now());
user.setLocalDateTimeFormat(LocalDateTime.now());
return user;
}
}
默认返回
没有任何配置,直接输出对象,可以得到一个如下的json数据(前端看了想打人)
{
"name":"tom",
"age":20,
"password":"123456",
"birthday":1677250587064,
"localDateTime":[ 2023, 2, 24, 22, 56, 27, 64000000],
"localDate":[ 2023, 2, 24],
"localTime":[ 22, 56, 27, 64000000],
"localDateTimeFormat":[ 2023, 2, 24, 22, 56, 27, 64000000]
}
或者(测试几次发现日期格式输出竟然不固定)
{
"name": "tom",
"age": 20,
"password": "123456",
"birthday": "2023-02-24T23:24:08.956+00:00",
"localDateTime": "2023-02-25T07:24:08.956",
"localDate": "2023-02-25",
"localTime": "07:24:08.956",
"localDateTimeFormat": "2023-02-25T07:24:08.956"
}
默认返回数据有几个问题:
- 密码字段
password
不需要返回 - 时间格式
Date
返回的是13位时间戳 - 时间格式
LocalDateTime
、LocalDate
、LocalTime
返回的是数组格式 - 字段名是小驼峰个格式,大部分情况需要返回蛇形的下划线小写格式
通过配置格式化
添加配置
spring:
jackson:
date-format: yyyy-MM-dd HH:mm:ss
time-zone: GMT+8
返回数据
{
"name": "tom",
"age": 20,
"password": "123456",
"birthday": "2023-02-25 07:25:56",
"localDateTime": "2023-02-25T07:25:56.509",
"localDate": "2023-02-25",
"localTime": "07:25:56.51",
"localDateTimeFormat": "2023-02-25T07:25:56.51"
}
可以看到,只有Date
类型的birthday
参数生效了
通过注解实现属性设置
通过几个注解,实现实体对象转为json的属性设置
注解 | 作用 |
---|---|
@JsonIgnoreProperties | 批量设置转 JSON 时忽略的属性 |
@JsonIgnore | 转 JSON 时忽略当前属性 |
@JsonProperty | 修改转换后的 JSON 的属性名 |
@JsonFormat | 转 JSON 时格式化属性的值 |
返回对象实体
package com.example.demo.dto;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.Date;
@Data
public class User {
private String name;
private Integer age;
// 忽略属性
@JsonIgnore
private String password;
// 修改属性名
@JsonProperty("birthDay")
private Date birthday;
private LocalDateTime localDateTime;
private LocalDate localDate;
private LocalTime localTime;
// 格式化
@JsonFormat(pattern = "yyyy年MM月dd日")
private LocalDateTime localDateTimeFormat;
}
返回结果
{
"name": "tom",
"age": 20,
"localDateTime": "2023-02-25T07:32:57.637",
"localDate": "2023-02-25",
"localTime": "07:32:57.637",
"localDateTimeFormat": "2023年02月25日",
"birthDay": "2023-02-25 07:32:57"
}
通过以上配置,我们实现了
- 不返回密码字段
password
- 自定义了字段
localDateTimeFormat
的时间格式 - 自定义了字段
birthday
的命名风格改为了小驼峰形式birthDay
目前为止,localDateTime
和localTime
还没有处理到
全局配置
继承WebMvcConfigurationSupport类,覆写方法
protected void extendMessageConverters(List<HttpMessageConverter<?>> converters){}
WebMvcConfig
package com.example.demo.config;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
import java.util.List;
@Configuration
@Slf4j
public class WebMvcConfig extends WebMvcConfigurationSupport {
/**
* 扩展消息转换器
*
* @param converters
*/
@Override
protected void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
// 创建消息转换器对象
MappingJackson2HttpMessageConverter messageConverter = new MappingJackson2HttpMessageConverter();
// 设置对象转换器
messageConverter.setObjectMapper(new JacksonObjectMapper());
// 添加到mvc框架消息转换器中,优先使用自定义转换器
converters.add(0, messageConverter);
}
}
JacksonObjectMapper
package com.example.demo.config;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.PropertyNamingStrategies;
import com.fasterxml.jackson.databind.deser.std.DateDeserializers;
import com.fasterxml.jackson.databind.ser.std.DateSerializer;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import static com.fasterxml.jackson.databind.DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES;
/**
* 对象映射器:基于jackson将Java对象转为json,或者将json转为Java对象
* 将JSON解析为Java对象的过程称为 [从JSON反序列化Java对象]
* 从Java对象生成JSON的过程称为 [序列化Java对象到JSON]
*/
public class JacksonObjectMapper extends ObjectMapper {
private static final String DEFAULT_DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
private static final String DEFAULT_DATE_FORMAT = "yyyy-MM-dd";
private static final String DEFAULT_TIME_FORMAT = "HH:mm:ss";
public JacksonObjectMapper() {
super();
// 收到未知属性时不报异常
this.configure(FAIL_ON_UNKNOWN_PROPERTIES, false);
// 统一返回数据的输出风格 转为蛇形命名法
this.setPropertyNamingStrategy(new PropertyNamingStrategies.SnakeCaseStrategy());
// 反序列化时,属性不存在的兼容处理
this.getDeserializationConfig()
.withoutFeatures(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
// 格式化时间
JavaTimeModule module = new JavaTimeModule();
module.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_TIME_FORMAT)))
.addDeserializer(LocalDate.class, new LocalDateDeserializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_FORMAT)))
.addDeserializer(LocalTime.class, new LocalTimeDeserializer(DateTimeFormatter.ofPattern(DEFAULT_TIME_FORMAT)))
.addDeserializer(Date.class, new DateDeserializers.DateDeserializer())
// .addSerializer(, )
// .addSerializer(, )
.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_TIME_FORMAT)))
.addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_FORMAT)))
.addSerializer(LocalTime.class, new LocalTimeSerializer(DateTimeFormatter.ofPattern(DEFAULT_TIME_FORMAT)))
.addSerializer(Date.class, new DateSerializer(false, new SimpleDateFormat(DEFAULT_DATE_TIME_FORMAT)))
;
// 注册功能模块 添加自定义序列化器和反序列化器
this.registerModule(module);
}
}
最终效果
{
"name": "tom",
"age": 20,
"local_date_time": "2023-02-25 07:56:22",
"local_date": "2023-02-25",
"local_time": "07:56:22",
"local_date_time_format": "2023年02月25日",
"birthDay": "2023-02-25 07:56:22"
}
至此,我们解决了一开始的几个格式问题
完整代码: /spring-boot-demo/#/SpringBoot-JSON/README
参考
- Spring Boot——统一设置返回Json数据风格(Java驼峰命名法转下划线命名法)解决方案
- Springboot JSON 转换:Jackson篇
- Jackson解决序列化LocalDateTime到接口中变成数组(Spring boot)