1. Jackson 序列化注解
1.1 @JsonAnyGetter
JsonAnyGetter 标记方法可以将返回的对象展开。这个注解标记的返回值必须是java.util.Map
@AllArgsConstructor
public static class ExtendableBean {
public String name;
private Map<String, String> properties;
@JsonAnyGetter
public Map<String, String> getProperties() {
return properties;
}
}
@Test
public void s1() throws JsonProcessingException {
ExtendableBean bean = new ExtendableBean("lupeng", new HashMap<>());
bean.properties.put("attr1", "val1");
bean.properties.put("attr2", "val2");
String json = new ObjectMapper().writeValueAsString(bean);
System.out.println(json);
// {"name":"lupeng","attr2":"val2","attr1":"val1"}
}
1.2 @JsonGetter
JsonGetter 将标记的getter方法序列化为json的属性
@AllArgsConstructor
public static class MyBean {
private int id;
private String name;
@JsonGetter(value = "name")
public String getTheName1() {
return name;
}
// other getter setter
}
@Test
public void s2() throws JsonProcessingException {
MyBean bean = new MyBean(111, "aaa");
String result = new ObjectMapper().writeValueAsString(bean);
System.out.println(result);
//{"id":111,"name":"aaa"}
}
1.3 @JsonPropertyOrder
@JsonPropertyOrder 指定属相的序列化顺序
@JsonPropertyOrder(alphabetic=true) 属性的序列化方式为字母顺序
@AllArgsConstructor
@JsonPropertyOrder(value = {"name", "id"})
// {"name":"aaa","id":111}
public static class MyBean {
private int id;
private String name;
@JsonGetter(value = "name")
public String getTheName1() {
return name;
}
}
1.4 @JsonRawValue
@JsonRawValue 标记的属性不做转移处理
@Data
@AllArgsConstructor
public static class MyBean1 {
private int id;
@JsonRawValue
private String value;
}
@Test
public void s3() throws JsonProcessingException {
MyBean1 bean1 = new MyBean1(1, "{"attr":false}");
String result = new ObjectMapper().writeValueAsString(bean1);
System.out.println(result);
// {"id":1,"value":{"attr":false}}
}
1.5 @JsonValue
@JsonValue 作用于整个实例,注释getName以便任何此类实体都通过其名称进行序列化 一个类只能由一个此注解,多个会报错
@AllArgsConstructor
public enum TypeEnumWithValue {
TYPE1(1, "Type A"), TYPE2(2, "Type 2");
private Integer id;
private String name;
@JsonValue
public String getName() {
return name;
}
//@JsonValue
//public Integer getId() {
// return id;
//}
}
@Test
public void s4() throws JsonProcessingException {
TypeEnumWithValue type1 = TypeEnumWithValue.TYPE1;
System.out.println(new ObjectMapper().writeValueAsString(type1));
// "Type A"
}
1.6 @JsonRootName
@JsonRootName 作用于整个对象,注释的对象自动设置根属相, 要使用这个功能需要开启
objectMapper.enable(SerializationFeature.WRAP_ROOT_VALUE);
@Data
@AllArgsConstructor
@JsonRootName(value = "user")
public static class MyBean2 {
private int id;
private String name;
}
@Test
public void s5() throws JsonProcessingException {
MyBean2 bean2 = new MyBean2(1, "222");
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.enable(SerializationFeature.WRAP_ROOT_VALUE);
System.out.println(objectMapper.writeValueAsString(bean2));
// {"user":{"id":1,"name":"222"}}
}
1.7 @JsonSerialize(using = **.class)
@JsonSerialize 指定序列化这个属性的序列化器,支持自定义序列化器
@Data
@AllArgsConstructor
public static class MyBean3 {
private int id;
private String name;
@JsonSerialize(using = CustomSerialize.class)
private SuperBean superBean;
}
public static class SuperBean {}
public static class CustomSerialize
extends StdSerializer<SuperBean> {
public CustomSerialize() {
this(null);
}
public CustomSerialize(Class<SuperBean> t) {
super(t);
}
@Override
public void serialize(SuperBean superBean, JsonGenerator jsonGenerator,
SerializerProvider serializerProvider) throws IOException {
jsonGenerator.writeString("Im super bean");
}
}
@Test
public void s6() throws JsonProcessingException {
MyBean3 bean3 = new MyBean3(1, "33", new SuperBean());
ObjectMapper objectMapper = new ObjectMapper();
System.out.println(objectMapper.writeValueAsString(bean3));
// {"id":1,"name":"33","superBean":"Im super bean"}
}
2. Jackson 反序列化注解
2.1 @JsonCreator
@JsonCreator 标记反序列的构造函数或者工厂
@Data
public static class Bean1 {
public int id;
public String name;
@JsonCreator
public Bean1(
@JsonProperty("id") int id,
// 这个类中没有这个属性
@JsonProperty("theName") String name) {
this.id = id;
this.name = name;
}
}
@Test
public void s1() throws JsonProcessingException {
String json = """
{
"id":1,
"theName":"My bean"
}
""".strip();
Bean1 bean1 = objectMapper.readValue(json, Bean1.class);
System.out.println(bean1);
}
2.2 @JsonAnySetter
@JsonAnySetter 在反序列化的时候将没有映射到的属性放到Map中
@Data
public static class Bean2 {
public int id;
public String theName;
private Map<String, Object> properties = new HashMap<>();
// 将没有匹配到的字段放到Map中
@JsonAnySetter
public void add(String k, Object v) {
properties.put(k, v);
}
}
@Test
public void s2() throws JsonProcessingException {
String json = """
{
"id":1,
"theName":"My bean",
"attr1":"val1",
"attr2": {
"k1":"v1"
}
}
""".strip();
Bean2 bean2 = objectMapper.readValue(json, Bean2.class);
System.out.println(bean2);
}
2.3 @JsonSetter
@JsonSetter 当我们需要读取一些 JSON 数据但目标实体类与该数据不完全匹配时,这个注解可以将不匹配的字段解析。
2.4 @JsonDeserialize
@JsonDeserialize 使用自定义的反序列化器
@Data
public static class Bean3 {
public int id;
@JsonDeserialize(using = CustomDeserialize.class)
public String theName;
}
public static class CustomDeserialize extends StdDeserializer<String> {
public CustomDeserialize() {
this(null);
}
public CustomDeserialize(Class<String> t) {
super(t);
}
@Override
public String deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JacksonException {
String text = p.getText();
return "CustomDeserialize: " + text;
}
}
@Test
public void s3() throws JsonProcessingException {
String json = """
{
"id":1,
"theName":"My bean"
}
""".strip();
Bean3 bean3 = objectMapper.readValue(json, Bean3.class);
System.out.println(bean3);
}
3.5 @JsonAlias
@JsonAlias 别名,反序列化的时候可以将指定的别名匹配到的属性序列化
public static class Bean4 {
public int id;
public String firstName;
@JsonAlias(value = {"fName", "first_name"})
public void setFirstName(String firstName) {
this.firstName = firstName;
}
}
@Test
public void s4() throws JsonProcessingException {
String json = """
{
"id":1,
"first_name":"My bean"
}
""".strip();
Bean4 bean4 = objectMapper.readValue(json, Bean4.class);
System.out.println(bean4);
}
3. Jackson 属性相关的注解
3.1 @JsonIgnoreProperties、@JsonIgnore、@JsonIgnoreType
在序列化和方序列化时设置忽略的属性
@JsonIgnoreProperties 注释在类上指定多个忽略的属性
@JsonIgnore 注释在属性上
@JsonIgnoreType 带有此注解的类型忽略
public class User {
public int id;
public Name name;
// 忽略name
@JsonIgnoreType
public static class Name {
public String firstName;
public String lastName;
}
}
3.2 @JsonInclude
@JsonInclude 可以设置排除 null/空/默认值的属性
@AllArgsConstructor
@JsonInclude(JsonInclude.Include.NON_NULL)
public class Bean5 {
public int id;
public String name;
}
@Test
public void s5() throws JsonProcessingException {
Bean5 bean5 = new Bean5(1, null);
System.out.println(objectMapper.writeValueAsString(bean5));
// {"id":1,"name":null} 不开启
// {"id":1} 开启之后
}
3.3 @JsonAutoDetect
@JsonAutoDetect 属性访问级别,设置哪些访问级别可以被序列化
@AllArgsConstructor
@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY)
//@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.DEFAULT)
public class PrivateBean {
private int id;
private String name;
}
@Test
public void s6() throws JsonProcessingException {
PrivateBean bean = new PrivateBean(1, "aaa");
System.out.println(objectMapper.writeValueAsString(bean));
// JsonAutoDetect.Visibility.DEFAULT {}
// JsonAutoDetect.Visibility.ANY {"id":1,"name":"aaa"}
}
3.4 @JsonProperty
@JsonProperty 用来标记序列化和反序列化时属性的名字
3.5 @JsonFormat
@JsonFormat 处理时间的格式化
@Data
@AllArgsConstructor
public class EventWithFormat {
public String name;
@JsonFormat(
shape = JsonFormat.Shape.STRING,
pattern = "yyyy-MM-dd HH:mm:ss",
timezone = "GMT+8")
public Date eventDate;
}
@Test
public void s8() throws JsonProcessingException {
EventWithFormat event = new EventWithFormat("aa", new Date());
System.out.println(objectMapper.writeValueAsString(event));
// {"name":"aa","eventDate":"2022-04-10 12:34:26"} 时间和当前时间对不上
// 添加 timezone = "GMT+8" 之后时间正确
}
3.6 @JsonUnwrapped
@JsonUnwrapped 标记的属性在序列化时展开
@Data
@AllArgsConstructor
public class UnwrappedUser {
public int id;
@JsonUnwrapped
public Name name;
@Data
@AllArgsConstructor
public static class Name {
public String firstName;
public String lastName;
}
}
@Test
public void s9() throws JsonProcessingException {
// serialize
UnwrappedUser user = new UnwrappedUser(1, new UnwrappedUser.Name("zhang", "san"));
System.out.println(objectMapper.writeValueAsString(user));
//{"id":1,"firstName":"zhang","lastName":"san"}
}
4. Jackson 多态
一段json文本,可以根据一个字段来区分序列化成哪个具体的实现类,
下面一个例子。动物园包含动物,根据type 字段来确定是哪种动物。
@Data
public static class Zoo {
private Animal animal;
}
@Data
@JsonTypeInfo(
use = JsonTypeInfo.Id.NAME,
property = "type"
)
@JsonSubTypes({
@JsonSubTypes.Type(value = Dog.class, name = "dog"),
@JsonSubTypes.Type(value = Cat.class, name = "cat")
})
public abstract static class Animal {
public String name;
public abstract void call();
}
@Data
@JsonTypeName("cat")
public static class Cat extends Animal {
@Override
public void call() {
System.out.println("喵喵喵");
}
}
@Data
@JsonTypeName("dog")
public static class Dog extends Animal {
@Override
public void call() {
System.out.println("汪汪汪");
}
}
@Test
public void s7() throws JsonProcessingException {
String json = """
{
"animal": {
"name": "花花",
"type": "cat"
}
}
""".strip();
Zoo zoo = objectMapper.readValue(json, Zoo.class);
zoo.animal.call();
}
5. Jackson 读写json
5.1 反序列化json数组
使用 new TypeReference<List>() {} 标记
@NoArgsConstructor
@AllArgsConstructor
public static class Bean1 {
private int id;
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
/**
* 将对象序列化为json
*/
@Test
public void s1() throws JsonProcessingException {
String json = """
[{"id":11, "name":"peng"},{"id":111, "name":"guo"}]
""".strip();
List<Bean1> list = objectMapper.readValue(json, new TypeReference<List<Bean1>>() {});
System.out.println(list);
}
5.2 反序列化json为java.util.Map
也是使用new TypeReference<Map<String, Object>>() {}
public class Test {
@Test
public void s2() throws JsonProcessingException {
String json = """
{"id":111, "name":"guo"}
""".strip();
Map<String, Object> map = objectMapper.readValue(json, new TypeReference<Map<String, Object>>() {
});
System.out.println(map);
}
}