目录
环境:
1.驼峰转下划线配置
1.1单个字段命名转化使用@JsonProperty注解
1.2单个类进行命名转化使用@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class)注解
3.全局命名策略配置
2. 序列化以及反序列化
2.1序列化
2.2反序列化
3.自定义序列化与反序列化
在Web开发中,JSON(JavaScript Object Notation)成为了一种广泛使用的前后端、服务端与服务端的交互的数据格式,主要用于前后端数据传输和存储。
1.Java是一种面向对象编程语言,而JSON是一种键值对格式的数据,因此在Java中,需要将Java对象转换为JSON字符串,或者将JSON字符串转换为Java对象。这个过程就是JSON的序列化和反序列化。
2.在生产过程中由于命名规范的问题,前后端交互往往使用的是下划线的方式进行出入参,而java项目中的实体类中的参数命名规则一般是小驼峰命名,所以在前后端交互过程中需要进行下划线转驼峰的配置。
对于Java中的JSON序列化和反序列化,有很多开源库可供选择,其中Jackson库是最受欢迎的之一。Jackson库提供了丰富的功能,可以实现灵活的JSON序列化和反序列化,而且性能非常出色。
环境:
jdk:1.8
springboot版本:2.7.15
spingboot依赖中已经集成了Jackson相关依赖
1.驼峰转下划线配置
jackson对驼峰转下划线配置有3个作用域的配置,分别是单个字段,单个类以及全局配置。
1.1单个字段命名转化使用@JsonProperty注解
首先我们创建一个UInfo实体类
package com.iterge.iterge_pre.entity;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
/**
* @author liuph
* @date 2023/9/22 11:07:12
*/
@Data
public class UInfo {
@JsonProperty("first_name")
private String firstName;
private String lastName;
private Integer age;
}
接口返回测试:
package com.iterge.iterge_pre.controller;
import com.iterge.iterge_pre.entity.TUser;
import com.iterge.iterge_pre.entity.UInfo;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* <p>
* 前端控制器
* </p>
*
* @author iterge
* @since 2023-09-05
*/
@RestController
@RequestMapping("/tUser")
public class TUserController {
@GetMapping("test")
public UInfo get(){
UInfo uInfo = new UInfo();
uInfo.setFirstName("san");
uInfo.setLastName("zhang");
uInfo.setAge(20);
return uInfo;
}
}
结果:
1.2单个类进行命名转化
使用@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class)注解
修改UInfo类:
package com.iterge.iterge_pre.entity;
import com.fasterxml.jackson.databind.PropertyNamingStrategies;
import com.fasterxml.jackson.databind.annotation.JsonNaming;
import lombok.Data;
/**
* @author liuph
* @date 2023/9/22 11:07:12
*/
@Data
@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class)
public class UInfo {
//@JsonProperty("first_name")
private String firstName;
private String lastName;
private Integer age;
}
package com.iterge.iterge_pre.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serializable;
/**
* <p>
*
* </p>
*
* @author iterge
* @since 2023-09-05
*/
@TableName("user_info")
public class UserInfo implements Serializable {
private static final long serialVersionUID = 1L;
@TableId(value = "id", type = IdType.AUTO)
private Long id;
private String firstName;
private String age;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
@Override
public String toString() {
return "UserInfo{" +
"id = " + id +
", firstName = " + firstName +
", age = " + age +
"}";
}
}
接口测试结果:
上面两图可以观察到UInfo输出是下划线,而UserInfo还是驼峰。
3.全局命名策略配置
全局命名策略配置5种,需要在yml文件中设置spring.jackson.property-naming-strategy: SNAKE_CASE
策略 | 例子 | 备注 |
---|---|---|
LOWER_CAMEL_CASE | firstName | 默认策略 小驼峰命名 |
UPPER_CAMEL_CASE | FirstName | 大驼峰命名 |
KEBAB_CASE | first-name | 短横线命名 |
LOWER_CASE | firstname | 全小写命名 |
SNAKE_CASE | first_name | 下划线命名 |
配置:
spring:
profiles:
active: dev
jackson:
property-naming-strategy: SNAKE_CASE
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
#mapper-locations: classpath:mapper/*Mapper.xml
修改UInfo类,注释@JsonNaming:
package com.iterge.iterge_pre.entity;
import com.fasterxml.jackson.databind.PropertyNamingStrategies;
import com.fasterxml.jackson.databind.annotation.JsonNaming;
import lombok.Data;
/**
* @author liuph
* @date 2023/9/22 11:07:12
*/
@Data
//@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class)
public class UInfo {
//@JsonProperty("first_name")
private String firstName;
private String lastName;
private Integer age;
}
测试结果:
由图可知两个接口输出都改成了“_”下划线的格式输出
2. 序列化以及反序列化
2.1序列化
将Java对象转换为JSON字符串最基本的方法就是使用ObjectMapper类的writeValueAsString方法。这个方法接收一个Java对象作为参数,返回一个JSON字符串。
序列化和反序列化也可以使用阿里开源的fastjson,使用教程:fastjson详解
package com.iterge.iterge_pre.mapper;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.iterge.iterge_pre.entity.UInfo;
import lombok.SneakyThrows;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
/**
* @author liuph
* @date 2023/9/22 11:09:15
*/
@SpringBootTest
public class JacksonTest {
ObjectMapper mapper = new ObjectMapper();
@SneakyThrows
@Test
public void test1(){
UInfo uInfo = new UInfo();
uInfo.setFirstName("san");
uInfo.setLastName("zhang");
uInfo.setAge(20);
System.out.println(mapper.writeValueAsString(uInfo));
}
}
2.2反序列化
将JSON字符串转换为Java对象的基本方法是使用ObjectMapper类的readValue方法。这个方法接收两个参数:一个JSON字符串和一个Java类,它会将JSON字符串反序列化为指定的Java类对象。
package com.iterge.iterge_pre.mapper;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.iterge.iterge_pre.entity.UInfo;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
/**
* @author liuph
* @date 2023/9/22 11:09:15
*/
@SpringBootTest
@Slf4j
public class JacksonTest {
ObjectMapper mapper = new ObjectMapper();
@SneakyThrows
@Test
public void test1(){
UInfo uInfo = new UInfo();
uInfo.setFirstName("san");
uInfo.setLastName("zhang");
uInfo.setAge(20);
System.out.println(mapper.writeValueAsString(uInfo));
}
@SneakyThrows
@Test
public void test2(){
String str = "{\"firstName\":\"san\",\"lastName\":\"zhang\",\"age\":20}";
UInfo uInfo = mapper.readValue(str, UInfo.class);
log.info("first name:{}",uInfo.getFirstName());
}
}
3.自定义序列化与反序列化
在某些情况下,Jackson库提供的默认序列化和反序列化行为可能无法满足需求,需要自定义序列化和反序列化规则。例如,在序列化UInfo对象时,我们希望将年龄按字符串类型序列化,而不是默认的整型类型。
新建序列化方法IntToStringSerializer
package com.iterge.iterge_pre.config;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import java.io.IOException;
/**
* @author liuph
* @date 2023/9/22 14:17:07
*/
public class IntToStringSerializer extends JsonSerializer<Integer> {
@Override
public void serialize(Integer integer, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
jsonGenerator.writeString(integer.toString());
}
}
对UInfo对象age字段添加注解@JsonSerialize(using = IntToStringSerializer.class)
package com.iterge.iterge_pre.entity;
import com.fasterxml.jackson.databind.PropertyNamingStrategies;
import com.fasterxml.jackson.databind.annotation.JsonNaming;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.iterge.iterge_pre.config.IntToStringSerializer;
import lombok.Data;
/**
* @author liuph
* @date 2023/9/22 11:07:12
*/
@Data
//@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class)
public class UInfo {
//@JsonProperty("first_name")
private String firstName;
private String lastName;
@JsonSerialize(using = IntToStringSerializer.class)
private Integer age;
}
测试: