一、Java常见的序列化与饭序列化工具
1、jackson(springboot默认的序列化工具),jackson底层采用的是ObjectMapper技术进行序列化以及反序列化的。
2、alibaba-fastjson。
二、SpringBoot日期格式序列化(特定讲一下)
1、SpringBoot默认是可以接受时间戳格式自动转换成java.util.Date。默认是不支持字符串自动转成java.util.Data。
2、SpringBoot如何接收字符串自动转换成java.util.Date
2.1 全局处理方式 (配置文件)。
#Spring默认接收时间戳进行反序列化到Date。这样就可以同时支持时间戳或者自定义的字符串格式日期转java.util.Date
spring.jackson.date-format=yyyy-MM-dd HH:mm:ss
#jackson默认的时区是Greenwich Time,我们所处的是东八区
spring.jackson.time-zone=GMT+8
接受请求
输出格式
2.2 具体字段具体处理方式
@JsonFormat这里会覆盖前面配置文件的格式 用于application/json的时候
@DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss") 用于表单multipart/form-data提交的方式
public class DataDTO {
private String name;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") //用于application/json 可以决定序列化以及发序列化的格式
//@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") //用于multipart/form-data表单提交方式 只能决定反序列化的格式
private Date create;
private Integer count;
private String cA;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Date getCreate() {
return create;
}
public void setCreate(Date create) {
this.create = create;
}
public Integer getCount() {
return count;
}
public void setCount(Integer count) {
this.count = count;
}
public String getcA() {
return cA;
}
public void setcA(String cA) {
this.cA = cA;
}
}
三、SpringBoot默认jackson序列化工具常用注解
1、序列化以及反序列化都会生效注解
1.1、@JsonIgnoreProperties(value = {"name"},ignoreUnknown = true)
ignoreUnknown = true的作用
@JsonIgnoreProperties(value = {"name"},ignoreUnknown = true)
public class DataDTO {
private String name;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date create;
private Integer count;
private String cA;
......set get......
}
public static void main(String[] args) throws JsonProcessingException {
String json = "{\n" +
" \"name\": \"testName\",\n" +
" \"create\": \"2021-07-02 08:46:53\",\n" +
" \"count\": 6,\n" +
" \"cA\": \"testCA\",\n" +
" \"cB\": \"testCA\"\n" +
"}";
ObjectMapper mapper = new ObjectMapper();
DataDTO dataDTO = mapper.readValue(json, DataDTO.class);
System.out.println(dataDTO);
}
如上代码如果不加ignoreUnknown=true则会出现以下异常,但是经过实际测试多字段会出现一下异常,少字段不会出现以下异常。
1.2、@JsonProperty("name")
用在属性上以及GET/SET方法上,如果用在属性上那么GET/SET都将已属性上的name为准。
如果用在GET/SET上则,各自用各自的name处理,至于未找的属性值则为null处理。
另外@JsonProperty直接注释在属性上的话,没有GET/SET都会被序列化的。但是alibab fast json序列化需要GET/SET方法。
@JsonProperty会强制private变成public,所以将会以注解的实际名称处理。
/*
* 情况一
*/
@JsonProperty("cA")
private String cA;
public String getCA(){
return cA;
}
public void setCA(String cA){
this.cA = cA;
}
/*
* 情况二
*/
public String cA;
public String getCA(){
return cA;
}
public void setCA(String cA){
this.cA = cA;
}
以上两种情况都会出现下面这种情况
由上可以推测SpringBoot在对象的序列化以及反序列化的时候,是已GET/SET后面的字符串决定的。如果是public属性则会出现GET以及属性本身的名称值。如果是private属性则只会序列化GET标准的名称。
属性本身的值以及GET方法解析出来的属性值会存放在HashMap当中。对于private的则不会序列化出来,这也就是为什么会出现上面的情况。如果是标准的GET饿会和属性本身名称重名,而且属性本身是private也会移除。public则会重名HashMap中只会保留GET解析出来的名称属性。
特殊情况命名方式为xAxx方式,例如aA则会出现getAA然后解析出来aa属性,所以会出现aa,aA两个属性。
jackson2对pojo类型序列化的处理。
Jackson2在初始化序列器时,对pojo类型对象会收集其属性信息,属性包括成员变量及方法,然后属性名称和处理过后的方法名称做为key保存到一个LinkedHashMap中。
收集过程中会调用com.fasterxml.jackson.databind.util.BeanUtil中的legacyManglePropertyName方法用来处理方法名称,它会将get/set方法前缀,即get或set去掉,并将其后面的连续大写字符转换成小写字符返回。
例如: getNEWString会转变成newstring返回。你的属性名称如果有这样的"nSmallSellCount",lombok自动生成的get方法就会是这样的"getNSmallSellCount",处理过后就是这样的"nsmallSellCount",这与属性nSmallSellCount并不冲突,
可以同时存在于HashMap中。收集完属性信息后,下面的步骤中会删除掉非可见的属性,一般指的是私有成员变量,这时,名称为"nSmallSellCount"的成员变量属性会被删除掉,这样的序列化结果是不会有问题的,但,如果加了@JsonProperty注释,
Jackson2会认为这个属性是可见的,不必会删除,这时这两个表示同一个值得属性就会被一同序列化。
所以在使用lombok的时候出现aAbbb或者aABBb类似的情况要注意。
@Data
public class LombokDTO {
private String aAbbb;
private String aABBb;
}
其实实际aAbbb但是按照lombok应该序列化的是aabbb而不是aAbbb;
所以大家在用lombok的时候要注意,不要被假象所迷惑以实际测试为准。另外发现lombok使用@Builder和@Data的时候默认会没有空构造函数的。需要空构造函数不需同时加上以下注解
@Data
@Builder
@NoArgsConstructor //提供默认无参构造函数
public class LombokDTO {
private String aAbbb;
public static void main(String[] args) {
new LombokDTO();
}
}