一、Java常见的序列化与饭序列化工具

1、jackson(springboot默认的序列化工具),jackson底层采用的是ObjectMapper技术进行序列化以及反序列化的。

2、alibaba-fastjson。

 

二、SpringBoot日期格式序列化(特定讲一下)

1、SpringBoot默认是可以接受时间戳格式自动转换成java.util.Date。默认是不支持字符串自动转成java.util.Data。

spring boot json 序列化 名字 springboot默认序列化_json

spring boot json 序列化 名字 springboot默认序列化_序列化_02

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

接受请求

spring boot json 序列化 名字 springboot默认序列化_反序列化_03

 输出格式

spring boot json 序列化 名字 springboot默认序列化_json_04

 

2.2 具体字段具体处理方式

@JsonFormat这里会覆盖前面配置文件的格式 用于application/json的时候

spring boot json 序列化 名字 springboot默认序列化_json_05

 

 

spring boot json 序列化 名字 springboot默认序列化_json_06

@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)

spring boot json 序列化 名字 springboot默认序列化_反序列化_07

 

spring boot json 序列化 名字 springboot默认序列化_json_08

 

 

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则会出现以下异常,但是经过实际测试多字段会出现一下异常,少字段不会出现以下异常。

spring boot json 序列化 名字 springboot默认序列化_json_09

 1.2、@JsonProperty("name")

 用在属性上以及GET/SET方法上,如果用在属性上那么GET/SET都将已属性上的name为准。

如果用在GET/SET上则,各自用各自的name处理,至于未找的属性值则为null处理。

spring boot json 序列化 名字 springboot默认序列化_反序列化_10

 

 

 

spring boot json 序列化 名字 springboot默认序列化_反序列化_11

 

 

 另外@JsonProperty直接注释在属性上的话,没有GET/SET都会被序列化的。但是alibab fast json序列化需要GET/SET方法。

spring boot json 序列化 名字 springboot默认序列化_反序列化_12

 

 

@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;
}

以上两种情况都会出现下面这种情况

spring boot json 序列化 名字 springboot默认序列化_反序列化_13

 

 由上可以推测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;
}

spring boot json 序列化 名字 springboot默认序列化_反序列化_14

其实实际aAbbb但是按照lombok应该序列化的是aabbb而不是aAbbb;

 

 

spring boot json 序列化 名字 springboot默认序列化_序列化_15

所以大家在用lombok的时候要注意,不要被假象所迷惑以实际测试为准。另外发现lombok使用@Builder和@Data的时候默认会没有空构造函数的。需要空构造函数不需同时加上以下注解

@Data
@Builder
@NoArgsConstructor //提供默认无参构造函数
public class LombokDTO {

    private String aAbbb;

    public static void main(String[] args) {
           new LombokDTO();
    }
}