0%

JSON Jackson序列化库 注解篇

Jackson 是一个简单的、功能强大的、基于 Java 的应用库。它可以很方便完成 Java 对象和 Json 对象进行互转。Jackson社区相对比较活跃,更新速度也比较快。

Jackson库有如下几大特性:

  1. 高性能且稳定:低内存占用,对大/小JSON串,大/小对象的解析表现均很优秀
  2. 流行度高:是很多流行框架的默认选择
  3. 容易使用:提供高层次的 API,极大简化了日常使用案例
  4. 无需自己手动创建映射:内置了绝大部分序列化时和 Java 类型的映射关系
  5. 干净的 JSON:创建的 JSON 具有干净、紧凑、体积小等特点
  6. 无三方依赖:仅依赖于 JDK
  7. Spring生态加持:Jackson 是 Spring 家族的默认 JSON/XML 解析器

通用注解

JsonIgnore

方法、字段上均可使用

指定被注解的变量或者方法不参与序列化和反序列化操作。

JsonIgnoreProperties

类上可用

参数 解释 备注
value 忽略指定字段
ignoreUnknown 忽略JSON内有但POJO内没有的字段 默认会报错
allowGetters 开放 value 中指定字段的 get 权限
allowSetters 开放 value 中指定字段的 set 权限

JsonIgnoreType

类上可用

忽略该类型的序列化/反序列化操作。

@Data   
public class OrderTb {  
  
  
    private Integer id;  
  
    private User buyer;  
  
    private User seller;  
  
    @JsonIgnoreType  
    @Data    
    public static class User {  
        private String name;  
	}
}    
OrderTb tb = new OrderTb();  
tb.setId(1);
tb.setBuyer(new Buyer())

String w = mapper.writerFor(OrderTb.class).writeValueAsString();

// 最终序列化为 {"id":1}

"{\"id\":\"1\"}"

JsonAutoDetect

类上可用

指定getter、setter、is-getter、字段的可见性,用来序列化/反序列化时是否包含某种访问权限的字段。

参数 解释 备注
getterVisibility getter可见性
isGetterVisibility is-getter可见性
setterVisibility setter可见性
creatorVisibility 开放 value 中指定字段的 set 权限
fieldVisibility 字段可见性
枚举 解释
ANY 私有、默认、保护、公共 四种权限都可见
NON_PRIVATE 默认、保护、公共 三种权限都可见
PROTECTED_AND_PUBLIC 保护、公共 两种权限都可见
PUBLIC_ONLY 仅 公共 权限可见
NONE 都不可见
DEFAULT 从父配置中获取

JsonTypeInfo (Todo)

字段、方法、参数、类可用

参数 解释 备注
use
include
property 插入额外信息的名称(不设置采用默认值)
defaultImpl
visible

多态序列化反序列化场景

@Data  
//@JsonTypeInfo(use = Id.CLASS)  
public class Shape {  
    private String name;  
}

@Data  
@EqualsAndHashCode(callSuper = true)  
public class Circle extends Shape {  
    private Integer radius;  
}

@Data  
@EqualsAndHashCode(callSuper = true)  
public class Rectangle extends Shape {  
    private Integer width;  
    private Integer height;  
}
Circle circle = new Circle();  
circle.setName("circle");  
circle.setRadius(10);  
  
Rectangle rectangle = new Rectangle();  
rectangle.setName("rectangle");  
rectangle.setHeight(2);  
rectangle.setWidth(5);  
  
ObjectMapper mapper = new ObjectMapper();  

String circleJson = mapper.writer().writeValueAsString(circle);  
// {"name":"circle","radius":10}
String rectangleJson = mapper.writer().writeValueAsString(rectangle);  
// {"name":"rectangle","width":5,"height":2}

Shape circleObj = mapper.readerFor(Shape.class).readValue(circleJson);  
Shape rectangleObj = mapper.readerFor(Shape.class).readValue(rectangleJson);  
  
System.out.println(circleObj);  
System.out.println(rectangleObj);

反序列化时会因为字段未填充报错。

在父类定义上面加上 @JsonTypeInfo(use = Id.CLASS) 注解之后,序列化的输出结果如下

{
	"@class":"com.example.springdemo.Circle",
	"name":"circle",
	"radius":10
} 
{
	"@class":"com.example.springdemo.Rectangle",
	"name":"rectangle",
	"width":5,
	"height":2
}

@JsonTypeInfo 注解不仅可以加在父类的定义上面,也可以加到包含父类的成员变量上面。当在集合类型(List,Map,Array)上使用时,它将应用于元素,而不是集合本身。

@JsonTypeInfo(use = Id.CLASS) 
private List<Shape> shapes;

反序列化后,Shape 类型可正常类型转换为子类。

序列化相关注解

JsonGetter

方法可用

根据指定的 Value 值,序列化对应的 getter 方法。

@JsonGetter("orderSeq")
public Integer getId() {  
    return id;  
}

// 将 id 字段序列化为 orderSeq

JsonAnyGetter

方法、字段可用

将 Map 中的 KV,直接映射成该类的属性。

@Data  
public class OrderTb {  
  
    private Integer id;  
  
    private String orderSeq;

	@JsonIgnore
	@JsonAnyGetter 
    private Map<String, Object> properties;
}
ObjectMapper mapper = new ObjectMapper();  
  
OrderTb tb = new OrderTb();  
tb.setProperties(Collections.singletonMap("orderSeq", "150204"));  
String w = mapper.writerFor(OrderTb.class).writeValueAsString(tb);  
// {"orderSeq":null, "orderSeq":"150204"} 
// 如果Map中Key和POJO字段重复则会序列化出两个字段,且字段生成的优先级低,读取时覆盖优先级高的。
OrderTb r = mapper.readerFor(OrderTb.class).readValue(w);  
// OrderTb(orderSeq=150204)

JsonPropertyOrder

类上可用

指定序列化输出顺序。

JsonFormat

字段、方法、参数可用

指定序列化日期的格式。

@Data  
public class OrderTb { 
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")  
    private Date time;
}

JsonRawValue

使用该注解的字段或者方法,都会被序列化,但是序列化结果是原始值。(一般用来序列化本身就是JSON字符串的内容)

@Data  
public class OrderTb {  
  
    private Integer id;  
  
    @JsonRawValue  
    private String orderSeq;
}
OrderTb tb = new OrderTb();  
tb.setId(1);  
tb.setOrderSeq("150204");   

String s = mapper.writerFor(OrderTb.class).writeValueAsString(tb);

// 最终序列化为 {"id":1,"orderSeq":1111}

JsonValue

方法、字段可用

在序列化类时,直接返回对应字段或方法内容。

@Data  
public class OrderTb {

	private Integer id;
	
	@JsonValue  
	public String toJson() {  
	    return "json value annotation test";  
	}
}

// 最终序列化为 json value annotation test

序列化枚举类型场景

public enum TargetTypeEnum implements Enumerator{
    INNER_H5(0,"内置H5"),
    INNER_APP(1,"内置APP模块"),
    OUTER_APP(2,"三方APP"),
    OUTER_H5(3,"三方H5");
	
	@JsonValue
    private Integer code;
    private String desc;
    
    TargetTypeEnum(int code,String desc) {
        this.code=code;
        this.desc=desc;
    }
}

// 在被序列化时会被直接序列化为Code值

JsonSerialize

用于在Java对象指定一个字段的自定义序列化器。

参数 解释 备注
using
contentUsing
keyUsing
nullsUsing
as
keyAs
contentAs
typing
converter
contentConverter

反序列化相关注解

JsonSetter

字段、方法、参数 可用

参数 解释 备注
value 从json中定义参数接收内容
nulls 字段反序列化时为空策略
contentNulls 字段是包装类型如(Map,Collection,array)时,内容反序列化时为空策略

nulls 以及 contentNulls 可以指定以下空值处理策略

枚举 解释
SET
SKIP 跳过反序列化对应内容
FAIL 对应字段反序列化时为null会报错
AS_EMPTY 对应字段反序列化时为null会填充空字符串或空的结构体
DEFAULT

JsonAnySetter

方法、字段可用

POJO 类中有的字段会被反序列化到对应位置,其他字段会被 SET 到指定的 Map 中。

@Data  
public class OrderTb {  
  
    private Integer id;  
  
    @JsonAnySetter  
    private Map<String, String> properties = new HashMap<>();
}
OrderTb r = mapper.readerFor(OrderTb.class).readValue("{\"id\":\"1\",\"orderSeq\": 150204}");

// 最终反序列化为 OrderTb(id=1, properties={orderSeq=150204})

JsonProperty (Todo)

方法、字段上均可使用

参数 解释
value 转换序列化、反序列化时的名称
namespace
required
index 改变序列化后在JSON中放置的顺序
defaultValue
access

JsonAlias

方法、字段上均可使用

反序列化时可以让 Bean 的属性接收多个 JSON 字段的名称。

JacksonInject

反序列化时可以让 Bean 的属性接收提前设置好的默认值。

ObjectMapper mapper = new ObjectMapper();  
// 可以按照指定值和指定class的形式映射默认值
InjectableValues.Std injects = new Std();  
// 将默认 defaultBuyer 为 key 的值设置为 Amy
injects.addValue("defaultBuyer", "Amy");  
// 将默认 String 类型的值设置为 default string
injects.addValue(String.class, "default string");  
mapper.setInjectableValues(injects);
@Data  
public class OrderTb {  
 
    private Integer id;  
  
    @JacksonInject("defaultBuyer")  
    private String buyer;  
  
    @JacksonInject  
    private String seller;  
}
OrderTb s = mapper.readerFor(OrderTb.class).readValue("{\"id\":\"1\"}");  

// 最终反序列化为 OrderTb(id=1, buyer=Amy, seller=default string)

JsonDeserialize

参数 解释 备注
using
contentUsing
keyUsing
as
keyAs
contentAs
builder
converter
contentConverter

未调研注解

JsonBackReference
JsonClassDescription
JsonCreator
JsonEnumDefaultValue
JsonFilter
JsonIdentityInfo
JsonIdentityReference
JsonInclude
JsonIncludeProperties
JsonKey
JsonManagedReference
JsonMerge
JsonPropertyDescription
JsonRootName
JsonSubTypes
JsonTypeId
JsonTypeName
JsonView
JacksonStdImpl
JsonAppend
JsonNaming
JsonPOJOBuilder
JsonTypeIdResolver
JsonTypeResolver
JsonValueInstantiator