jackson
jackson 的使用
引入包
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core -->
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-core</artifactId>
    <version>2.13.1</version>
</dependency>创建需要序列化的对象
@Data
public class Student {
    private String name;
    private Integer age;
    private Date birthday;
    private LocalDateTime start;
}序列化
public class jacksonTest {
    private static ObjectMapper objectMapper = new ObjectMapper();
    static {
        // 设置JSON包含
        objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
    }
    @Test
    void jacksonTest(){
        Student student = new Student();
        student.setAge(20);
        student.setBirthday(new Date());
        student.setStart(LocalDateTime.now());
        objectMapper.writerWithDefaultPrettyPrinter()
    }
}处理NULL值
设置JSON是否包含null,有两种方式
- 全局方式 - objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
- 针对某一个类,使用注解 - @JsonInclude(JsonInclude.Include.NON_NULL)
@Data
@JsonInclude(JsonInclude.Include.NON_NULL)
public class Student {
    private String name;
    private Integer age;
    private Date birthday;
    private LocalDateTime start;
}处理Date格式
针对一个属性
在Bean对象的属性上使用@JsonFormat(pattern = "yyyy-MM-dd",timezone = "GMT+8")注解
@Data
public class Student {
    @JsonInclude(JsonInclude.Include.NON_NULL)
    private String name;
    private Integer age;
    @JsonFormat(pattern = "yyyy-MM-dd",timezone = "GMT+8")
    private Date birthday;
    @JsonFormat(pattern = "yyyyMMdd HH:mm:ss",timezone = "GMT+8")
    private LocalDateTime start;
}标记完运行发现LocalDateTime类型对应的start是没有被序列化成想要的字符串

需要引入一个jsr310的包,是jackson对LocalDateTime等jar8时间日期处理的Model
 在jackson中是作为Model生效的,Model需要注册。
- 先引入jsr310的包
<dependency>
    <groupId>com.fasterxml.jackson.datatype</groupId>
    <artifactId>jackson-datatype-jsr310</artifactId>
    <version>2.13.1</version>
</dependency>- 注册
public class JasksonTest {
    private static ObjectMapper objectMapper = new ObjectMapper();
    static {
        // 设置JSON包含
        objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
        // 自动通过SPI发现jackson的modle并注册
        objectMapper.findAndRegisterModules();
    }
    @Test
    void jasksonTest() throws JsonProcessingException {
        Student student = new Student();
        student.setAge(20);
        student.setBirthday(new Date());
        student.setStart(LocalDateTime.now());
        System.out.println(objectMapper.writeValueAsString(student));;
    }
}- 再次查看

LocalDateTime设置全局
public class JasksonTest {
    private static ObjectMapper objectMapper = new ObjectMapper();
    static {
        // 设置JSON包含
        objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
        JavaTimeModule javaTimeModule = new JavaTimeModule();
        // 反序列化时使用
        javaTimeModule.addDeserializer(LocalDateTime.class,
            new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern("yyyyMMdd HH:mm:ss")));
        // 序列化时使用
        javaTimeModule.addSerializer(LocalDateTime.class,
            new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyyMMdd HH:mm:ss")));
        objectMapper.registerModule(javaTimeModule);
    }
    @Test
    void jasksonTest() throws JsonProcessingException {
        Student student = new Student();
        student.setAge(20);
        student.setBirthday(new Date());
        student.setStart(LocalDateTime.now());
        System.out.println(objectMapper.writeValueAsString(student));;
    }
}查看

注意
LocalDateTime的时间格式是到yyyyMMdd HH:mm:ss的如果只是yyyyMMdd,反序列化会报错
Cannot deserialize value of type java.time.LocalDateTime from String "20220124"
Date类型也可以但不建议使用objectMapper.setDateFormat(new SimpleDateFormat("yyyyMMdd HH:mm:ss"));
 SimpleDateFormat不是线程安全的,而ObjectMapper是线程安全的。这样设置导致ObjectMapper线程不安全。
美化输出
objectMapper.configure(SerializationFeature.INDENT_OUTPUT,true);
反序列化
忽略不存在的key
objectMapper.configure(DeserializationFeature.FAIL_ON_IGNORED_PROPERTIES,false);
泛型
public class JasksonTest {
    private static ObjectMapper objectMapper = new ObjectMapper();
    static {
        // 设置JSON包含
        objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
//        objectMapper.findAndRegisterModules();
        JavaTimeModule javaTimeModule = new JavaTimeModule();
//        // 反序列化时使用
        javaTimeModule.addDeserializer(LocalDateTime.class,
            new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern("yyyyMMdd HH:mm:ss")));
//        // 序列化时使用
        javaTimeModule.addSerializer(LocalDateTime.class,
            new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyyMMdd HH:mm:ss")));
        objectMapper.registerModule(javaTimeModule);
        // 美化输出
        objectMapper.configure(SerializationFeature.INDENT_OUTPUT,true);
        // 反序列化时忽略不存在的key
        objectMapper
            .configure(DeserializationFeature.FAIL_ON_IGNORED_PROPERTIES,false);
    }
    @Test
    void jasksonTest() throws JsonProcessingException {
        Student student = new Student();
        student.setAge(20);
        student.setBirthday(new Date());
        student.setStart(LocalDateTime.now());
        ResponseDataBase<Student> response = new ResponseDataBase<>();
        response.setData(student);
        response.successful();
        String data = objectMapper.writeValueAsString(response);
        System.out.println(data);
        ResponseDataBase<Student> dataResult = 
        objectMapper
            .readValue(data, new TypeReference<ResponseDataBase<Student>>() {});
        System.out.println(dataResult.getData().toString());
    }
}定制
驼峰转下划线
设置策略 userName 转成 user_name 输出// 蛇形命名法objectMapper.setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE);
指定属性名称
使用注解@JsonProperty("address")
指定忽略属性
使用注解@JsonIgnore
使用Jackson做对象更新
对象更新,对象的合并。如果后者属性有值,则用后者,否则的值不变。
@Test
void jasksonTest2() throws JsonProcessingException {
    Student orgUser = new Student();
    orgUser.setName("user1");
    orgUser.setAge(20);
    orgUser.setBirthday(new Date());
    Student newUser = new Student();
    newUser.setName("user1");
    newUser.setAge(22);
    Student student = objectMapper.updateValue(orgUser, newUser);
    System.out.println(student.toString());
}age值被更新

遇到匈牙利命名法如何使用jackson序列化
匈牙利命名法(Hungarian notation),由1972年至1981年在施乐帕洛阿尔托研究中心工作的-程序员 查尔斯·西蒙尼发明,这位前辈后面成了微软的总设计师。
这个命名法的特点是,在命名前面增加类型的前缀,就像这样:
- c_name - 姓名,字符串(Char)类型
- n_age - 年龄,数字(Number)类型
- t_birthday - 生日,日期/时间(Time)类型
可不要小看这个命名法,当年可是很流行的,而且直到今天还是有一些系统仍然在沿用这个命名标准,比如微软的 Win32 API
重构目标,是要保持老系统表不动的情况下,完全重写。新系统是 Java 语言来开发,Java 可是驼峰命名标准的,当这个匈牙利命名法的表迁移到驼峰命名法的 Java 语言会怎么样?
比如 c_name 这个命名,到 Java 里之后,是改为 CName 呢,还是 cName 呢?好像怎么都有点奇怪,不过最后还是选择了 CName ,将类型的前缀完全大写,至少看着稍微正常一点,没那么反人类
- c_name -> CName
- n_age -> NAge
- t_birthday -> TBirthday
Jackson 很强大,支持配置属性的获取方式,可以配置 Visibility 来实现只通过 Field 而不通过 getter 来获取属性:
@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, getterVisibility = JsonAutoDetect.Visibility.NONE)
public class Book {
    private Integer NId = 1;
    private String CName = "John";
}全局配置更方便:
ObjectMapper objectMapper = new ObjectMapper();
// 配置 field 为可见
objectMapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY);
// 配置 getter 不可见
objectMapper.setVisibility(PropertyAccessor.GETTER, JsonAutoDetect.Visibility.NONE);完~
#序列化