Jackson 提供的注解使用说明

Jackson注解主要分成三类:

一、只在序列化时生效的注解:

1. @JsonPropertyOrder

在将 java pojo 对象序列化成为 json 字符串时,使用 @JsonPropertyOrder 可以指定属性在 json 字符串中的顺序。

2. @JsonInclude

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

@JsonInclude(JsonInclude.Include.NON_NULL)
这个注解放在类头上,返给前端的json里就没有null类型的字段,即实体类与json互转的时候 属性值为null的不参与序列化。
另外还有很多其它的范围,例如 NON_EMPTY、NON_DEFAULT等

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;


@JsonInclude(JsonInclude.Include.NON_NULL)
public class WithdrawDetail implements Serializable {

}

或者

WithdrawDetail wd = new WithdrawDetail();

wd.setSerializationInclusion(Include.NON_NULL);

二、只在反序列化时候生效的注解:

1. @JsonSetter

@JsonSetter 标注于 setter 方法上,类似 @JsonProperty ,也可以解决 json 键名称和 java pojo 字段名称不匹配的问题。

三、两种情况下都生效的注解。

public class SomeEntity {
    private String desc;
    @JsonSetter("description")
    public void setDesc(String desc) {
        this.desc = desc;
    }
}

上述例子中在将 json 字符串转换成 SomeEntity 实例时,会将 json 字符串中的 description 字段赋值给 SomeEntity 的 desc 属性。

@JsonIgnore

作用域属性或方法上,@JsonIgnore 用来告诉 Jackson 在处理时忽略该注解标注的 java pojo 属性, 不管是将 java 对象转换成 json 字符串,还是将 json 字符串转换成 java 对象。

@Data
public class SellerInfoEntity {

    private String id;
    private String username;
    private String password;
    private String openid;

    @JsonIgnore
    private Timestamp createTime;
    @JsonIgnore
    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;
    }
}

@JsonIgnoreProperties

作用在类上,@JsonIgnoreProperties 和 @JsonIgnore 的作用相同,都是告诉 Jackson 该忽略哪些属性, 不同之处是 @JsonIgnoreProperties 是类级别的,并且可以同时指定多个属性。

@Data
@JsonIgnoreProperties(value = {"createTime","updateTime"})
public class SellerInfoEntity {

    private String id;
    private String username;
    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;
    }
}

@JsonIgnoreType

@JsonIgnoreType 标注在类上,当其他类有该类作为属性时,该属性将被忽略。

package org.lifw.jackosn.annotation;
import com.fasterxml.jackson.annotation.JsonIgnoreType;
@JsonIgnoreType
public class SomeOtherEntity {
    private Long id;
    public Long getId() {
        return id;
    }
    public void setId(Long id) {
        this.id = id;
    }
}
public class SomeEntity {
    private String name;
    private String desc;
    private SomeOtherEntity entity;
}

@JsonProperty

@JsonProperty 可以指定某个属性和json映射的名称。例如我们有个json字符串为{“user_name”:”aaa”},
而java中命名要遵循驼峰规则,则为userName,这时通过@JsonProperty 注解来指定两者的映射规则即可。这个注解也比较常用。

public class SomeEntity {
    @JsonProperty("user_name")
    private String userName;
      // ...
}

@JsonIgnoreProperties(ignoreUnknown = true)

Jackson解析JSON数据时,忽略未知的字段。(如果不设置,当JSON字段和bean字段不匹配时,会抛出异常)

    static class Book {
        String name;
        String price;
    }

例一

这样一个类,如果json 字符串中的字段数量多于类的字段,如:

        String bookJson3 = "{\"name\":\"d2\", \"price\":\"1\", \"sn\":\"222\"}";
        Book b3 = mapper.readValue(bookJson3, Book.class);

那么报错如下:

com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field
 "sn" (class com.example.demo.DemoApplicationTests2$Book),
 not marked as ignorable (2 known properties: "price", "name"])
 
 at [Source: (String)"{"name":"d2", "price":"1", "sn":"222"}"; line: 1, column: 34] 
(through reference chain: com.example.demo.DemoApplicationTests2$Book["sn"])

给Book 类增加注解:

@JsonIgnoreProperties(ignoreUnknown = true)

可以解决这个问题。

例二

如果 json 字符串中的字段少了是可以正常工作的,如

        String bookJson = "{\"name\":\"dd\"}";
        Book b = mapper.readValue(bookJson, Book.class);
 
        System.out.println(b.name);
        System.out.println(b.price);

输出为:

dd
null

例三

        b = new Book();
        b.name = "hhg";
 
        System.out.println(mapper.writeValueAsString(b));

以上代码可以正常工作,输出为:

{"name":"hhg","price":null}

@JsonSerialize注解

我们做后端开发的有时候要返回给前端的数据格式不符合怎么办?

举个例子,比如一张表中的时间,数据库中存储的是yyy-mm-dd hh:mm:ss 这样的形式,而前段需要的是精确到秒的格式,那我们不可能直接把这种格式的数据直接返回给前端吧?!

直接返回回去会跟前端掐起来的。。。。那怎么办?从数据库查出来的时候去转换一下?。嗯可以,但是问题又来了,那我在A方法中查询要转换一下,B方法中要转换一下...

这样就会导致代码冗余。除了使用自定义工具类,还有一种方法更直接,那就是使用@JsonSerialize(com.fasterxml.jackson.databind.annotation.JsonSerialize)注解。

使用步骤:

1.在实体类中在要转换的字段上加上该注解,如下:

 /** 订单创建时间 */
    @JsonSerialize(using = DateToLongSerializer.class)
    private Date createTiem;

2.并指定一个格式化的类。如下:

public class DateToLongSerializer extends JsonSerializer<Date> {

    @Override
    public void serialize(Date date, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
        jsonGenerator.writeNumber(date.getTime() / 1000);
    }
}

 数据存储在数据库中的格式:

转换后的效果(返回给前端的json格式):

再介绍一个注解:

@JsonIgnore 该注解的作用是转成json时不返回给前端

不起作用的情况:

在项目中 当字段实体类为Long类型时 如果Long值超过前端js显示的长度范围时会导致前端回显错误

此时我们想到的解决方案是将Long值返回给前端时转为String,

但是我们又不想变更字段的类型,当然我们也不想额外添加新的字段。

这个时候我们可以用@JsonSerialize,在Json序列化的时候把Long自动转为String,

但是这里有个小坑,被转换的字段必须是包装类类型,否则会转换失败。
 

@JsonSerialize(using = ToStringSerializer.class)
private Long parentId;    //转化成功
@JsonSerialize(using = ToStringSerializer.class)
private long parentId;    //转化失败

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值