场景:
有的时候有这个的需求,接口返回给业务的时候需要输出全部字段,但是有的场景比如打日志的时候需要忽略某些字段,比如密码。
Jackson有忽略字段注解,@JsonIgnore 和 @JsonIgnoreProperties,但是这两个注解都是全局性的。
方案:
使用Jackson的AnnotationIntrospector实现通过自定义注解忽略属性。
- 自定义注解
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface LogIgnore {
}
- 创建日志Json工具类
@Slf4j
public class LogJsonUtils {
private static final ObjectMapper mapper = new ObjectMapper();
static {
mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
mapper.setAnnotationIntrospector(new JacksonAnnotationIntrospector() {
private static final long serialVersionUID = 1L;
@Override
public boolean hasIgnoreMarker(AnnotatedMember m) {
LogIgnore ann = _findAnnotation(m, LogIgnore.class);
return ann != null;
}
});
}
public static String toJson(Object obj) {
String retStr = "";
if (obj == null) {
return retStr;
}
try {
retStr = mapper.writeValueAsString(obj);
} catch (Exception e) {
log.error("Object to json failed!", e);
}
return retStr;
}
}
使用示例
- 定义两个Bean,
@Data
@Accessors(chain = true)
public static class User1 {
private String username;
//忽略password
@LogIgnore private String password;
private Integer age;
}
@Data
@Accessors(chain = true)
public static class User2 {
private String username;
private String password;
//忽略age
@LogIgnore private Integer age;
}
@Test
public void test3() {
User1 user1 = new User1().setUsername("zhangsan").setPassword("123456").setAge(36);
User2 user2 = new User2().setUsername("lisi").setPassword("123456").setAge(36);
List<Object> userList = new ArrayList<>();
userList.add(user1);
userList.add(user2);
System.out.println(LogJsonUtils.toJson(userList));
}
- 执行结果,User1忽略了password字段,User2忽略了age字段
[ {
"username" : "zhangsan",
"age" : 36
}, {
"username" : "lisi",
"password" : "123456"
} ]