使用com.fasterxml.jackson.annotation的注解

2024-08-01 23:18:32 浏览数 (2)

名词解释:

  • 序列化:将对象转换为 JSON 字符串
  • 反序列化:将 JSON 字符串转换为对象

一、@JsonIgnore:

  • 作用: 在json序列化时将java bean中的一些属性忽略掉,序列化和反序列化都受影响。一般标记在属性或者方法上,在返回的json数据就不包含该属性。
  • 场景模拟: 将一个User序列化成Json数据并返回给前台,当我们在User的password和email属性上添加@JsonIgnore注解时,即使后台给这两个属性赋值了,返回前台的Json也不包含它们。
  • 首先在pom.xml中添加依赖
代码语言:xml复制
<dependencies>
    <dependency>
        <groupId>tk.mybatis</groupId>
        <artifactId>mapper-core</artifactId>
        <version>1.0.4</version>
    </dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>2.9.6</version>
    </dependency>
</dependencies>
  • 创建实体类
代码语言:java复制
public class User {
    private String name;
    private String age;
    private String sex;
    @JsonIgnore           //添加JsonIgnore注解,返回时被忽略
    private String password;
    @JsonIgnore          //添加JsonIgnore注解,返回时被忽略
    private String email;
    public User() {}
 }
  • @JsonIgnore注解失效 如果注解失效,可能是因为你使用的是fastJson,尝试使用对应的注解来忽略字段,注解为:@JSONField(serialize = false),使用方法一样。
  • 补充: jackSon@JsonIgnore, @JsonIgnoreProperties and @JsonIgnoreType注解使用详解

这个注解是用在字段上,get或者set方法上,效果都是一样的,用来在实体类序列化和反序列化的时候忽略该字段字段。

二、@JsonIgnoreProperties

1、概念:

是类注解,作用是json序列化时将java bean中的一些属性忽略掉,序列化和反序列化都受影响。

2、用法:

@JsonIgnoreProperties(ignoreUnknown = true),将这个注解写在类上之后,就会忽略类中不存在的字段。

这个注解和@JsonIgnore注解功能是一样的,区别就是这个注解是用在类上面的,在需要的注解比较多的情况下,用来一次性定义忽略的字段如:

代码语言:java复制
@Data
@JsonIgnoreProperties(value = {"fullName", "comment"})
public class User {
    private String id;
    private String name;
    private String fullName;
    private String comment;
    private String mail;
    @JsonIgnore
    private String address;
    @JsonFormat(timezone = "GMT 8", pattern = "yyyy-MM-dd HH:mm:ss")
    private Date regDate;
    private Date reg2Date;
}

说明:User类的fullNamecomment字段会被@JsonIgnoreProperties注解忽略。address字段会被@JsonIgnore注解忽略。regDate会按照@JsonFormat(timezone = “GMT 8”, pattern = “yyyy-MM-dd HH:mm:ss”)进行格式转。

controller示例代码:

代码语言:java复制
@ApiOperation(value = "按用户id删除", notes="private")
@ApiImplicitParams({@ApiImplicitParam(name = "userId", defaultValue = "2", value = "userID", required = true, dataType = "string", paramType = "path"),})
@DeleteMapping(value = "/users/{userId}", produces = "application/json;charset=UTF-8")
public User delUser(@PathVariable String userId) {
    User user = (User)userSvc.deleteById(userId);
    log.info("rest del user={} by id={}", user, userId);
    return user;
}

可以看到返回的对象是User,然后comment、fullName、address属性被忽略了,regDate的格式进行转换。

三、@JsonFormat

  • 作用:
    • Date和String的相互转化
    • 时差调整
  • 使用场景
    • 一般后台传值给前台时
    • 在我们中国来讲和我们的北京时间,会相差8个小时,因为我们是东八区(北京时间)。所以我们在格式化的时候要指定时区(timezone )

Date和String的自动转化

代码语言:java复制
 import com.fasterxml.jackson.annotation.JsonFormat;
    /**
     * 后台返给前台时, 日期自动格式化
     */
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date birth;

指定时区:

代码语言:java复制
/**更新时间  用户可以点击更新,保存最新更新的时间。**/
@JsonFormat(pattern="yyyy-MM-dd HH:mm:ss",timezone="GMT 8")
private Date updateTime;

四、@JsonInclude

在将 java pojo 对象序列化成为 json 字符串时,使用 @JsonInclude 注解可以控制在哪些情况下才将被注解的属性转换成 json,例如只有属性不为 null 时。

代码语言:java复制
@JsonInclude(JsonInclude.Include.NON_NULL)         //类前面使用,如果为空则不反悔该属性json
public class SellerInfoEntity {
 
    private String id;
    private String username;
 
    @JsonInclude(JsonInclude.Include.NON_EMPTY)   //属性前使用,如果为空则不返回该属性json
    private String password;
    private String openid;
    private Timestamp createTime;
    private Timestamp updateTime;
 
    public SellerInfoEntity() {
    }
 
    public SellerInfoEntity(String id, String username, String password, String openid) {
        this.id = id;
        this.username = username;
        this.password = password;
        this.openid = openid;
    }
}

五、@JsonSerialize

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

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

代码语言:java复制
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;

import java.io.IOException;

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

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

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

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

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

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

代码语言:java复制
serialize(T value, JsonGenerator gen, SerializerProvider serializers):

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

常使用的using以及nullsUsing

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

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

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

  • nullsUsing: 该属性用于指定在属性值为 null 时使用的序列化器。
  • xx.class: 自定义的序列化器类,它实现了 Jackson 的 JsonSerializer 接口,定义了处理 null 值的序列化逻辑。

代码如下:

代码语言:java复制
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. 重用性: 可以将自定义序列化器用于多个类,提高代码的重用性。

案例:

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

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

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

5.1 jsontest1

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

对于序列化的方式如下:

代码语言:java复制
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);


    }
}

截图如下:

5.2 jsontest2

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

代码语言:java复制
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("");
    }
}

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

代码语言:java复制
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);
    }
}

如果代码为如下:

代码语言:java复制
class CustomDate {
    @JsonSerialize(using = CustomDateSerializer.class)
    private Date date;

    public  CustomDate(){}

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

    public Date getDate() {
        return date;
    }
}

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

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

代码语言:java复制
class CustomDate {
    @JsonSerialize(nullsUsing = CustomDateSerializer.class)
    private Date date;

    public  CustomDate(){}

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

    public Date getDate() {
        return date;
    }
}

截图如下所示:

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

六、@JsonDeserialize用法

@JsonDeserialize可以在对象反序列化时执行自定义的代码,我们利用这个特性可以针对对象某个属性进行特性的处理。将特定格式的日期时间反序列化成LocalDateTime对象

属性

代码语言:java复制
@JsonDeserialize(using = LocalDateTimeFormmatDeserializa.class)
private LocalDateTime planInDate;

反序列化器

代码语言:java复制
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonNode;

import java.io.IOException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

public class LocalDateTimeFormmatDeserializa extends JsonDeserializer<LocalDateTime> {
    @Override
    public LocalDateTime deserialize(JsonParser p, DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
        JsonNode node = p.getCodec().readTree(p);
        // 之所以是用"yyyy-MM-dd'T'HH:mm:ss"这个格式解析成对象,是因为json字符串字段格式这样的
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss");
        LocalDateTime parse = LocalDateTime.parse(node.asText(), formatter);
        return parse;
    }
}

0 人点赞