文章目录
1. 常用注解
1.1 @JsonIgnore、@JsonIgnoreProperties
- 用@JsonIgnore注释后的字段,在json序列化时将java bean中的一些属性忽略掉,序列化和反序列化都受影响。
import com.fasterxml.jackson.annotation.JsonIgnore;
import java.io.Serializable;
public class DeptIdAndNameVO implements Serializable {
private static final long serialVersionUID = -73277829416320393L;
private String deptId;
private String deptName;
@JsonIgnore
private String parentId;
}
注:@JsonIgnore可以用在当getter和setter方法上,@JsonIgnore不管注解在getters上还是setters上都会忽略对应的属性
- 和 @JsonIgnore 的作用相同,都是告诉 Jackson 该忽略哪些属性,不同之处是 @JsonIgnoreProperties 是类级别的,并且可以同时指定多个属性。
@JsonIgnoreProperties(value = {“age”,“color”})
public class TestJackson{
private String id;
private String username;
private String password;
private Integer age;
private String color;
}
1.2 @JsonInclude(…)
这个注解表示,如果字段值为特定条件时,则不返回,可以在类上和属性上添加这个注释,当实体类与json互相转换的时候,属性值为特定条件的不参与序列化。
条件值可选:(填入@JsonInclude的括号中)
-
JsonInclude.Include.ALWAYS 默认
-
JsonInclude.Include.NON_DEFAULT 属性为默认值不序列化
-
JsonInclude.Include.NON_EMPTY 属性为 空("") 或者为 NULL 都不序列化
-
JsonInclude.Include.NON_NULL 属性为NULL 不序列化
1.3 @JsonProperty
@JsonProperty注解类似于sql里字段的别名,用于序列化,使用注解字段属性,替代原字段属性
@JsonProperty("userName")
private String name;
1.4 @JsonFormat
@JsonFormat注解格式化日期格式
@JsonFormat(pattern="yyyy-MM-dd HH:mm:ss",timezone="GMT+8")
private Date date;
1.5 @JsonTypeName @JsonTypeInfo
@JsonTypeName @JsonTypeInfo用在类上,在序列化时增加一层
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@JsonTypeName(value = "user")
@JsonTypeInfo(include = JsonTypeInfo.As.WRAPPER_OBJECT, use = JsonTypeInfo.Id.NAME)
public class User {
private Long id;
@JsonProperty("userName")
private String name;
private Integer age;
private Date birthday;
}
序列化结果:
{"user":{"id":1,"age":23,"birthday":1587891781603,"userName":"tom"}}
use
:定义使用哪一种类型识别码,它有下面几个可选值:1、JsonTypeInfo.Id.CLASS:使用完全限定类名做识别
2、JsonTypeInfo.Id.MINIMAL_CLASS:若基类和子类在同一包类,使用类名(忽略包名)作为识别码
3、JsonTypeInfo.Id.NAME:一个合乎逻辑的指定名称
4、JsonTypeInfo.Id.CUSTOM:自定义识别码,由@JsonTypeIdResolver对应,稍后解释
5、JsonTypeInfo.Id.NONE:不使用识别码
include
(可选):指定识别码是如何被包含进去的,它有下面几个可选值:1、JsonTypeInfo.As.PROPERTY:作为数据的兄弟属性
2、JsonTypeInfo.As.EXISTING_PROPERTY:作为POJO中已经存在的属性
3、JsonTypeInfo.As.EXTERNAL_PROPERTY:作为扩展属性
4、JsonTypeInfo.As.WRAPPER_OBJECT:作为一个包装的对象
5、JsonTypeInfo.As.WRAPPER_ARRAY:作为一个包装的数组
property
(可选):制定识别码的属性名称此属性只有当
use
为JsonTypeInfo.Id.CLASS(若不指定property则默认为@class)、JsonTypeInfo.Id.MINIMAL_CLASS(若不指定property则默认为@c)、JsonTypeInfo.Id.NAME(若不指定property默认为@type),include为JsonTypeInfo.As.PROPERTY、JsonTypeInfo.As.EXISTING_PROPERTY、JsonTypeInfo.As.EXTERNAL_PROPERTY时才有效
defaultImpl
(可选):如果类型识别码不存在或者无效,可以使用该属性来制定反序列化时使用的默认类型
visible
(可选,默认为false):是否可见属性定义了类型标识符的值是否会通过JSON流成为反序列化器的一部分,默认为fale,也就是说,jackson会从JSON内容中处理和删除类型标识符再传递给JsonDeserializer。
1.6 @JsonRootName
通过@JsonRootName来自定义根元素名称
需要配合配置SerializationFeature.WRAP_ROOT_VALUE
:是否环绕根元素,默认false,如果为true,则默认以类名作为根元素,你也可以通过@JsonRootName来自定义根元素名称。
objectMapper.configure(SerializationFeature.WRAP_ROOT_VALUE,true);
示例:
@JsonRootName("showPOJO")
public static class TestPOJO{
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
序列化结果:
{"showPOJO":{"name":"aaaa"}}
1.7 @JsonUnwrapped
作用在属性字段或方法上,用来将子JSON对象的属性添加到封闭的JSON对象。(序列化时,父对象 中被 该注解标记的对象类型的属性 中的属性不再被这个对象包裹,而是成为父对象的属性)
示例:
public class User{
@JsonUnwrapped
private BaseInfo baseInfo;
private String remake;
//set 和 get 省略
}
public class BaseInfo{
private String name;
private Integer age;
//set 和 get 省略
}
序列化结果:
{"name":"测试","age":12,"remake":"备注"}
在2.0+版本中@JsonUnwrapped添加了prefix和suffix属性,用来对字段添加前后缀,这在有关属性分组上比较有用,在上面的测试用例中,如果我们将TestPOJO的name属性上的@JsonUnwrapped添加前后缀配置,即
public class User{
@JsonUnwrapped
private BaseInfo baseInfo;
@JsonUnwrapped(prefix = "pre_",suffix = "_suf")
private BaseInfo baseInfo2;
private String remark;
//set 和 get 省略
}
序列化结果:
{
"name": "测试",
"age": 12,
"pre_name_suf": "测试",
"pre_age_suf": 12,
"remark": "备注"
}
1.8 @JsonView
视图模板,作用于方法和属性上,用来指定哪些属性可以被包含在JSON视图中,在前面我们知道已经有@JsonIgnore和@JsonIgnoreProperties可以排除过滤掉不需要序列化的属性,可是如果一个POJO中有上百个属性,比如订单类、商品详情类这种属性超多,而我们可能只需要概要简单信息即序列化时只想输出其中几个或10几个属性,此时使用@JsonIgnore和@JsonIgnoreProperties就显得非常繁琐,而使用@JsonView便会非常方便,只许在你想要输出的属性(或对应的getter)上添加@JsonView即可。
示例:
@Data
@AllArgsConstructor
public class View {
public interface View1{}
@JsonView(View1.class)
private String toShow;
private String noShow;
private String remark;
}
Controller中:
@JsonView(View.View1.class)
@GetMapping("/jackson3")
public View jackson3(){
return new View("show", "noShow", "备注");
}
结果:
{
"toShow": "show"
}
2. 工具类封装
package com.luqiao.cloud.security.util;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
/**
* @Author liangyixiang
* @Description 序列化工具(基于Jackson实现)
* @Date 2021/7/11
* @since JDK 11
**/
public class JsonUtil {
// 实例化ObjectMapper对象
private static ObjectMapper objectMapper = new ObjectMapper();
//日志记录
private static final Logger log = LoggerFactory.getLogger(JsonUtil.class);
// 赋值
static {
objectMapper
// 设置允许序列化空的实体类(忽略空Bean转json的错误)
.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS)
// 设置 把java.util.Date, Calendar输出为数字(时间戳)
//.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
// 设置在遇到未知属性的时候不抛出异常
//.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)
// 强制JSON 空字符串("")转换为null对象值
//.enable(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT)
// 设置数字丢失精度问题
.enable(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS)
// 设置没有引号的字段名
.enable(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES)
// 设置允许单引号
.enable(JsonParser.Feature.ALLOW_SINGLE_QUOTES)
// 忽略 在json字符串中存在,但是在java对象中不存在对应属性的情况。防止错误
.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, false);
}
/**
* 私有化构造器
*/
private JsonUtil(){}
/**
* @Author liangyixiang
* @Description 对象转Json格式字符串
* @Date 2021/7/11
* @param obj: 需序列化的对象
* @return: java.lang.String
**/
public static <T> String obj2String(T obj) {
if (obj == null) {
return null;
}
try {
return obj instanceof String ? (String) obj : objectMapper.writeValueAsString(obj);
} catch (JsonProcessingException e) {
log.warn("Parse Object to String error : {}", e.getMessage());
return null;
}
}
/**
* @Author liangyixiang
* @Description 对象转Json格式字符串(格式化的Json字符串)
* @Date 2021/7/11
* @param obj: 需序列化的对象
* @return: java.lang.String 美化的Json格式字符串
**/
public static <T> String obj2StringPretty(T obj) {
if (obj == null) {
return null;
}
try {
return obj instanceof String ? (String) obj : objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(obj);
} catch (JsonProcessingException e) {
log.warn("Parse Object to String error : {}", e.getMessage());
return null;
}
}
/**
* @Author liangyixiang
* @Description 字符串转换为自定义对象
* 调用示例: User user = JsonUtil.string2Obj(userJsonStr, User.class);
* @Date 2021/7/11
* @param str: 要转换的字符串
* @param clazz: 自定义对象的class对象
* @return: T 自定义对象
**/
public static <T> T string2Obj(String str, Class<T> clazz){
if(StringUtils.isEmpty(str) || clazz == null){
return null;
}
try {
return clazz.equals(String.class) ? (T) str : objectMapper.readValue(str, clazz);
} catch (Exception e) {
log.warn("Parse String to Object error : {}", e.getMessage());
return null;
}
}
/**
* @Author liangyixiang
* @Description 集合对象与Json字符串之间的转换
* 调用示例:List<User> userListBean = JsonUtil.string2Obj(userListJson, new TypeReference<List<User>>() {});
* @Date 2021/7/11
* @since JDK 11
* @param str: 要转换的字符串
* @param typeReference: 泛型抽象类
* @return: T
**/
public static <T> T string2Obj(String str, TypeReference<T> typeReference) {
if (StringUtils.isEmpty(str) || typeReference == null) {
return null;
}
try {
return (T) (typeReference.getType().equals(String.class) ? str : objectMapper.readValue(str, typeReference));
} catch (IOException e) {
log.warn("Parse String to Object error", e);
return null;
}
}
/**
* @Author liangyixiang
* @Description 集合对象与Json字符串之间的转换
* 调用示例:List<User> userListBean2 = JsonUtil.string2Obj(userListJson, List.class, User.class);
* @Date 2021/7/11
* @param str: 要转换的字符串
* @param collectionClazz: 集合类型
* @param elementClazzes: 实体类型
* @return: T
**/
public static <T> T string2Obj(String str, Class<?> collectionClazz, Class<?>... elementClazzes) {
JavaType javaType = objectMapper.getTypeFactory().constructParametricType(collectionClazz, elementClazzes);
try {
return objectMapper.readValue(str, javaType);
} catch (IOException e) {
log.warn("Parse String to Object error : {}" + e.getMessage());
return null;
}
}
}