如何自定义Jackson序列化 @JsonSerialize

 更新时间:2021年12月31日 08:50:01   作者:一笑而过者也  
这篇文章主要介绍了如何自定义Jackson序列化 @JsonSerialize,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

自定义Jackson序列化 @JsonSerialize

自定义json序列化需要实现StdSerializer<T>或者JsonSerializer<T>。

我要序列化House这个类,加上注解,指定用于序列化的类

package com.xhx.json.entity; 
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.xhx.json.serializers.HourseSerializer; 
import java.util.Date;
 
@JsonSerialize(using = HourseSerializer.class)
public class Hourse {
    private String location;
    private Date buildDate; 
    public String getLocation() {
        return location;
    }
 
    public void setLocation(String location) {
        this.location = location;
    }
 
    public Date getBuildDate() {
        return buildDate;
    }
 
    public void setBuildDate(Date buildDate) {
        this.buildDate = buildDate;
    }
}
package com.xhx.json.serializers; 
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
import com.xhx.json.entity.Hourse; 
import java.io.IOException;
 
public class HourseSerializer extends StdSerializer<Hourse> { 
    public HourseSerializer(){
        super(Hourse.class);
    }
 
    protected HourseSerializer(Class<Hourse> t) {
        super(t);
    }
 
    @Override
    public void serialize(Hourse hourse, JsonGenerator generator, SerializerProvider provider) throws IOException {
        generator.writeStartObject();
        generator.writeFieldName("id");
        generator.writeString("自定义");
        generator.writeFieldName("location");
        generator.writeString(hourse.getLocation());
        generator.writeObjectField("buildDate",hourse.getBuildDate());
        generator.writeEndObject();
    }
}

测试:

jackson自定义全局序列化、反序列化

需要自定义Jackson序列化和反序列化有两种方式,一种是全局定义,一种是非全局定义。先来看看全局定义。全局定义的步骤如下,以定义一个localDateTime的序列化和反序列化为例:

创建序列化类

创建一个序列化类然后继承JsonSerializer,重写serialize序列化方法。其中第一个参数localDateTime为JsonSerializer的泛型,表示的是被序列化的类型的值,第二个参数jsonGenerator表示的是用于输出生成的Json内容,第三个参数暂时没明白什么应用场景。重写方法一般是将想要序列化的字符串传入 jsonGenerator.writeString。

public final class LocalDateTimeSerializer extends JsonSerializer<LocalDateTime> {
    public static final LocalDateTimeSerializer INSTANCE = new LocalDateTimeSerializer(); 
    public LocalDateTimeSerializer() {
    }
    @Override
    public void serialize(LocalDateTime localDateTime, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException, JsonProcessingException {
        jsonGenerator.writeString(DateUtil.format(localDateTime, DateUtil.DateTimeFormatEnum.DATE_TIME_FORMAT_4));
    }
}

创建反序列化类

创建两个类,一个类继承JsonDeserializer,一个类继承KeyDeserializer,重写deserialize反序列化方法。参数jsonParser用于读取json内容的解析,deserializationContext可用于访问此有关反序列化的上下文(暂时也不知道怎么用),返回值则是JsonDeserializer的泛型对象,表示要反序列化的对象。一般用法是通过jsonParser.getText().trim()获取该字段json字符串,然后将该字符串转换为对象返回。

public final class LocalTimeDeserializer extends JsonDeserializer<LocalTime> {
    public static final LocalTimeDeserializer INSTANCE = new LocalTimeDeserializer(); 
    public LocalTimeDeserializer() {
    }
    @Override
    public LocalTime deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
        String text = jsonParser.getText().trim();
        return LocalTime.parse(text, DateUtil.DATE_TIME_FORMATTER_6);
    }
}
public final class LocalDateTimeKeyDeserializer extends KeyDeserializer {
    public static final LocalDateTimeKeyDeserializer INSTANCE = new LocalDateTimeKeyDeserializer(); 
    public LocalDateTimeKeyDeserializer() {
    }
    @Override
    public Object deserializeKey(String s, DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
        return StringUtils.isBlank(s) ? null : LocalDateTime.parse(s, DateUtil.DATE_TIME_FORMATTER_4);
    }
}

将两个类注册进入jackson核心对象objectMapper

@Bean
public ObjectMapper objectMapper(){
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        //不注释,会导致swagger报错
        //objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        //关闭日期序列化为时间戳的功能
        objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
        //关闭序列化的时候没有为属性找到getter方法,报错
        objectMapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
        //关闭反序列化的时候,没有找到属性的setter报错
        objectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
        //序列化的时候序列对象的所有属性
        objectMapper.setSerializationInclusion(JsonInclude.Include.ALWAYS);
        //反序列化的时候如果多了其他属性,不抛出异常
        objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        //如果是空对象的时候,不抛异常
        objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
        SimpleModule simpleModule = new SimpleModule();
        //json值序列化
        simpleModule.addSerializer(LocalDateTime.class, LocalDateTimeSerializer.INSTANCE);
        //json值反序列化
        simpleModule.addDeserializer(LocalDateTime.class, LocalDateTimeDeserializer.INSTANCE);
        //json键序列化
        simpleModule.addKeySerializer(LocalDateTime.class,LocalDateTimeSerializer.INSTANCE);
        //json键反序列化
        simpleModule.addKeyDeserializer(LocalDateTime.class, LocalDateTimeKeyDeserializer.INSTANCE);
        objectMapper.registerModule(simpleModule);
        return objectMapper;
    }

小结一下

以上,通过objectMapper的配置,完成了全局序列化、反序列化的配置,如果不需要全局则通过@jsonserialize或 @JsonDeserialize指定使用的序列化、反序列化类。仅为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家

相关文章

  • mybatis如何设置useGeneratedKeys=true

    mybatis如何设置useGeneratedKeys=true

    这篇文章主要介绍了mybatis如何设置useGeneratedKeys=true,具有很好的参考价值,希望对大家有所帮助。
    2022-01-01
  • Java如何连接数据库图文教程

    Java如何连接数据库图文教程

    关于java数据库的文章早已是非常多了,本文是对我个人过往学习java数据库,理解及应用java数据库的一个总结,下面这篇文章主要给大家介绍了关于Java如何连接数据库的相关资料,需要的朋友可以参考下
    2023-04-04
  • Java中使用WebSocket的几种方式

    Java中使用WebSocket的几种方式

    本文主要介绍了Java中使用WebSocket的几种方式
    2024-06-06
  • java IO流将一个文件拆分为多个子文件代码示例

    java IO流将一个文件拆分为多个子文件代码示例

    这篇文章主要介绍了java IO流将一个文件拆分为多个子文件代码示例,具有一定借鉴价值,需要的朋友可以参考下。
    2017-12-12
  • 学习Java内存模型JMM心得

    学习Java内存模型JMM心得

    这篇文章主要介绍了学习Java内存模型JMM的心得以及对其原理做了深入的介绍,有兴趣的朋友学习下吧。
    2017-12-12
  • springboot返回html和jsp的方法示例

    springboot返回html和jsp的方法示例

    这篇文章主要介绍了springboot返回html和jsp的方法示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-12-12
  • 基于SpringBoot实现大文件分块上传功能

    基于SpringBoot实现大文件分块上传功能

    这篇文章主要介绍了基于SpringBoot实现大文件分块上传功能,实现原理其实很简单,核心就是客户端把大文件按照一定规则进行拆分,比如20MB为一个小块,分解成一个一个的文件块,然后把这些文件块单独上传到服务端,需要的朋友可以参考下
    2024-09-09
  • java中JDeps命令使用

    java中JDeps命令使用

    jdeps是一个Java类依赖分析工具,用于分析Java应用程序的依赖情况,包括类、包、模块以及JDK内部API的使用,本文就来详细的介绍一下,感兴趣的可以了解一下
    2024-09-09
  • mybatis单笔批量保存实体数据的方法

    mybatis单笔批量保存实体数据的方法

    这篇文章主要介绍了mybatis单笔批量保存实体数据的相关知识,非常不错,具有参考借鉴价值,需要的朋友可以参考下
    2018-01-01
  • 解决idea删除模块后重新创建显示该模块已经被注册的问题

    解决idea删除模块后重新创建显示该模块已经被注册的问题

    这篇文章主要介绍了解决idea删除模块后重新创建显示该模块已经被注册的问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-02-02

最新评论