Java开发中POJO和JSON互转时如何忽略隐藏字段

Jackson相关:

使用Jackson相关的注解时一定要注意自己定义的属性命名是否规范。(命名规范
如果使用@JsonIgnore注解不起效时请注意一下你的属性名字是否规范

1、@JsonIgnoreProperties

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

1、忽略多个字段,配置value属性即可
2、忽略未知的属性,配置ignoreUnknowntrue,默认不忽略
3、允许忽略字段被序列化,配置allowGetterstrue,序列化的时候不会被忽略
4、允许忽略字段被反序列化,配置allowSetterstrue,反序列化的时候不会被忽略

// 生成json时将name和age属性过滤
@JsonIgnoreProperties({"name","age"})
public class  user {
	private  String name;
	private int age;
}

2、@JsonIgnore

2.1、常放在属性

作用:在json序列化时将Java Bean中的一些属性忽略掉,序列化和反序列化都受影响。

2.2、使用方法:

一般标记在属性或者方法上,返回的json数据即不包含该属性。
此注解用于属性或者方法上(最好是属性上),作用和上面的@JsonIgnoreProperties一样。生成json时不生成age属性。
也可以在类上加上注解@JsonIgnoreProperties(value = "{age}")

public class user {
	private  String name;
	@JsonIgnore
	private int age;
}

2.3、场景模拟:

需要把一个List<HistoryOrderBean>转换成json格式的数据传递给前台。但实体类中基本属性字段的值都存储在快照属性字段中。此时我可以在业务层中做处理,把快照属性字段的值赋给实体类中对应的基本属性字段。最后,我希望返回的json数据中不包含这两个快照字段,那么在实体类中快照属性上加注解@JsonIgnore,那么最后返回的json数据,将不会包含goodsInfoextendsInfo两个属性值。

public class HistoryOrderBean {

    //基本属性字段
    private String insurantName;
    private String insuranceName;
    private String insurancePrice;
    private String insurancePicture;
    private String insuranceLimit;

    //快照属性字段
    @JsonIgnore
    private String goodsInfo;      //快照基本信息
    @JsonIgnore
    private String extendsInfo;    //快照扩展属性信息

}

2.4、注解失效:

如果注解失效,可能是因为你使用的是fastJson,尝试使用对应的注解来忽略字段,注解为: @JSONField(serialize = false),使用方法一样。

要注意的是,当前端以json格式向后台传(如:age)值,且后台是以实体User接收时,这时候@JsonIgnore会忽略,即不接收age字段的值。若想避免此类情况,建议使用form表单的形式提交参数,而非json格式

3、@JsonProperty

需要Jackson版本不低于2.6
通常为了给Json的字段起别名或者设置默认值使用
比如UserInfo中的userId想对应JSON中的user_id,我们可以:

@JsonProperty(value = "user_id")
private String userId;

在2.6版本以后,这个注解也能实现忽略字段的作用。它有个access属性,用来指定在序列化(“读取”)和反序列化(“写”)期间访问权限(这里的读写是以属性为视角)。它由枚举Access定义:

public enum Access {
    /**
     * 无论是序列化还是反序列化都会根据配置自动的处理,默认值。
     */
    AUTO,

    /**
     * 意味着该属性只能在进行序列化时读取(通过“ getter”方法访问的值,或者从字段中读取),而在反序列化期间不能写入(设置)。
     * 换句话说,这将反映“只读POJO”,其中包含的值可以读取但不能写入。
     */
    READ_ONLY,

    /**
     * 意味着该属性只能作为反序列化的一部分写入(设置)(使用“ setter”方法,或分配给Field,或作为Creator参数传递),
     * 而不会被读取(获取)以进行序列化,即,该属性的值不包括在序列化中。
     */
    WRITE_ONLY,

    /**
     * 可读可写,READ_ONLY与WRITE_ONLY的合并效果。
     */
    READ_WRITE;
}

从这个注解中我们可以知道,如果你想在POJO转JSON时忽略secret字段,就可以这么写:

@JsonProperty( access = JsonProperty.Access.WRITE_ONLY)
private String secret;

4、@JsonFormat

此注解用于属性或者方法上(最好是属性上),可以方便的把Date类型直接转化为我们想要的模式,比如@JsonFormat(pattern = “yyyy-MM-dd HH-mm-ss”)

5、@JsonSerialize

此注解用于属性或者getter方法上,用于在序列化时嵌入我们自定义的代码,比如序列化一个double时在其后面限制两位小数点。

6、@JsonDeserialize

此注解用于属性或者setter方法上,用于在反序列化时可以嵌入我们自定义的代码,类似于上面的@JsonSerialize

7、@Transient

ORM框架将忽略该属性;
如果一个属性并非数据库表的字段映射,就务必将其标示为@Transient,否则ORM框架默认其注解为@Basic

transient的作用

我们都知道一个对象只要实现了Serilizable接口,这个对象就可以被序列化,java的这种序列化模式为开发者提供了很多便利,我们可以不必关系具体序列化的过程,只要这个类实现了Serilizable接口,这个类的所有属性和方法都会自动序列化。

然而在实际开发过程中,我们常常会遇到这样的问题,这个类的有些属性需要序列化,而其他属性不需要被序列化,打个比方,如果一个用户有一些敏感信息(如密码,银行卡号等),为了安全起见,不希望在网络操作(主要涉及到序列化操作,本地序列化缓存也适用)中被传输,这些信息对应的变量就可以加上transient关键字。换句话说,这个字段的生命周期仅存于调用者的内存中而不会写到磁盘里持久化。

总之,java 的transient关键字为我们提供了便利,你只需要实现Serilizable接口,将不需要序列化的属性前添加关键字transient,序列化对象的时候,这个属性就不会序列化到指定的目的地中。

transient使用小结

1)一旦变量被transient修饰,变量将不再是对象持久化的一部分,该变量内容在序列化后无法获得访问。

2)transient关键字只能修饰变量,而不能修饰方法和类。注意,本地变量是不能被transient关键字修饰的。变量如果是用户自定义类变量,则该类需要实现Serializable接口。

3)被transient关键字修饰的变量不再能被序列化,一个静态变量不管是否被transient修饰,均不能被序列化。

posted @ 2023-07-05 10:46  笔兴洽谈室  阅读(382)  评论(0编辑  收藏  举报