详细分析Java中的@JsonSerialize注解

目录

  • 前言
  • 1. 核心知识
  • 2. 基本知识
  • 3. Demo
    • 3.1 jsontest1
    • 3.2 jsontest2
  • 4. 总结

前言

对应序列化的相关知识可看我之前的文章:详解Java中的serialVersionUID概念以及作用(附上Demo)

详细分析Java中的@JsonSerialize注解_第1张图片

通过理解核心知识,再去品味总结的基本知识,可能理解更加透彻

对于序列化的场景,也可用于序列化JSON数据给前端的时候,某些值如果为空的时候,需要返回给前端的状态信息,对应需要使用到@JsonSerialize

1. 核心知识

@JsonSerialize 是 Jackson 库中的一个注解,用于指定在将 Java 对象序列化为 JSON 格式时,如何进行自定义的序列化处理。

通过这个注解,指定一个自定义的序列化器(serializer),以控制对象的序列化过程。

通过代码看总结:

import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;

import java.io.IOException;

// 继承 JsonSerializer 实现自定义序列化逻辑
public class CustomSerializer extends JsonSerializer<MyObject> {

    @Override
    public void serialize(MyObject value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
        // 在这里定义自己的序列化逻辑
        gen.writeString(value.toString());
    }
}

在Jackson库中,为了实现自定义的序列化逻辑,通常会创建一个类,该类继承自 JsonSerializer 接口或其子类。JsonSerializer 是一个泛型接口,其中的 表示要序列化的对象的类型。

继承 JsonSerializer 接口的主要目的是为了实现 serialize 方法,该方法定义了如何将指定类型的对象序列化为 JSON 格式。

通过继承该接口,提供自定义的序列化逻辑,从而满足特定对象的序列化需求。

具体来说,继承 JsonSerializer 需要实现以下方法:

serialize(T value, JsonGenerator gen, SerializerProvider serializers):

该方法定义了如何将对象 value 序列化为 JSON 格式,并使用 JsonGenerator 对象进行输出。

2. 基本知识

常使用的using以及nullsUsing

  • JsonSerialize 注解: 用于指定自定义序列化器的注解。
  • JsonSerializer 接口: 自定义序列化器需要实现这个接口,然后通过 @JsonSerialize 注解的 using 属性指定使用哪个序列化器。

该注解可以应用在类中,也可应用在属性中,对类的不同属性使用不同的序列化逻辑,从而更加灵活地控制 JSON 序列化的过程。

除了using的注解也还有nullsUsing 等注解,@JsonSerialize(nullsUsing = xx.class) 的含义是,当某个属性的值为 null 时,使用指定的自定义序列化器 xx.class 来处理该属性的序列化。

  • nullsUsing: 该属性用于指定在属性值为 null 时使用的序列化器。

  • xx.class: 自定义的序列化器类,它实现了 Jackson 的 JsonSerializer 接口,定义了处理 null 值的序列化逻辑。

示例代码如下:

import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;

import java.io.IOException;

// 自定义处理 null 值的序列化器
class NullSerializer extends JsonSerializer<Object> {

    @Override
    public void serialize(Object value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
        // 在这里定义处理 null 值的序列化逻辑
        gen.writeString("CustomNullValue");
    }
}

// 包含使用 @JsonSerialize 注解的类
class MyClass {
    // 当属性值为 null 时,使用 NullSerializer 处理序列化
    @JsonSerialize(nullsUsing = NullSerializer.class)
    private String nullableField;

    // 其他属性和方法...
}

在上述例子中,nullableField 属性上使用了 @JsonSerialize(nullsUsing = NullSerializer.class) 注解。当 nullableField 的值为 null 时,将使用 NullSerializer 类中定义的逻辑来处理该属性的序列化。

在这个例子中,处理 null 值的逻辑是将其序列化为字符串 "CustomNullValue"


总的来说,其作用如下:

  1. 定制化需求: 继承可以提供更大的灵活性,允许开发者完全控制序列化过程。
  2. 特定类型处理: 可以为不同类型的对象创建不同的序列化逻辑,以满足特定的业务需求。
  3. 重用性: 可以将自定义序列化器用于多个类,提高代码的重用性。

总的来说,通过继承 JsonSerializer 接口,开发者可以更加精细地控制对象的序列化过程,以适应各种复杂的场景和需求。

3. Demo

假设有一个包含日期信息的类 CustomDate,并且将其序列化为 JSON 格式时,按照特定的格式输出日期。

通过继承 JsonSerializer 来实现自定义的日期序列化逻辑。

注意看两个Demo的区分,分别应用在类或者属性上,以及使用using或者nullsUsing的区别!

3.1 jsontest1

注解应用在类上,且属性都会被序列化为某个特性:

对于序列化的方式如下:

package com.example.demo;

import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;

// 自定义序列化器
class CustomDateSerializer extends JsonSerializer<CustomDate> {

    private static final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    // 在这里定义自己的序列化逻辑
    @Override
    public void serialize(CustomDate customDate, JsonGenerator gen, SerializerProvider serializers) throws IOException {
        Date date = customDate.getDate();
        String formattedDate = dateFormat.format(date);
        gen.writeString(formattedDate);
    }
}



// 被序列化的对象
@JsonSerialize(using = CustomDateSerializer.class)
class CustomDate {

    private Date date;

    public  CustomDate(){}

    public CustomDate(Date date) {
        this.date = date;
    }

    public Date getDate() {
        return date;
    }
}

public class jsontest1 {
    public static void main(String[] args) throws IOException {
        // 创建一个 实例
        CustomDate customDate = new CustomDate(new Date());

        // 使用 Jackson 库将 MyObject 序列化为 JSON 字符串
        String json = new ObjectMapper().writeValueAsString(customDate);

        // 输出结果
        System.out.println(json);


    }
}

截图如下:

详细分析Java中的@JsonSerialize注解_第2张图片

3.2 jsontest2

对应序列化的类如下:(序列化的值为空!)

class CustomDateSerializer extends JsonSerializer<CustomDate> {

    private static final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    // 在这里定义自己的序列化逻辑
    @Override
    public void serialize(CustomDate customDate, JsonGenerator gen, SerializerProvider serializers) throws IOException {
        gen.writeString("");
    }
}

其运行的主函数如下:(注意传输的值为空!)

public class jsontest2 {
    public static void main(String[] args) throws IOException {
        // 创建一个 实例
        CustomDate customDate = new CustomDate();

        // 使用 Jackson 库将 MyObject 序列化为 JSON 字符串
        String json = new ObjectMapper().writeValueAsString(customDate);

        // 输出结果
        System.out.println(json);


    }
}

如果代码为如下:

class CustomDate {
    @JsonSerialize(using = CustomDateSerializer.class)
    private Date date;

    public  CustomDate(){}

    public CustomDate(Date date) {
        this.date = date;
    }

    public Date getDate() {
        return date;
    }
}

输出结果为:(这说明序列化失败),但注意如果这样放在类上,是可以成功的!

详细分析Java中的@JsonSerialize注解_第3张图片

为了在属性上可以序列化,应该使用如下方式:

class CustomDate {
    @JsonSerialize(nullsUsing = CustomDateSerializer.class)
    private Date date;

    public  CustomDate(){}

    public CustomDate(Date date) {
        this.date = date;
    }

    public Date getDate() {
        return date;
    }
}

截图如下所示:

详细分析Java中的@JsonSerialize注解_第4张图片

对应的将该注解放在类上,序列化可以成功!

4. 总结

  • using作用类,生效!
  • using在作用属性时,如果非空属性值的序列化转换,值为null,序列化不生效。需要使用nullsUsing来实现

你可能感兴趣的:(java,java,序列化,JsonSerialize)