Jackson的序列化
@JsonValue
注解
@JsonValue
可以用在get方法或者属性字段上,一个类只能用一个,当加上@JsonValue注解时,序列化时只返回这一个字段的值,而不是这个类的属性键值对。
Teacher.class
package org.zpli.springdemo.bean;
import com.fasterxml.jackson.annotation.JsonValue;
import lombok.Getter;
import lombok.Setter;
/**
* created at 2021/6/3 3:38 下午
*
* @author somnuszpli
*/
@Setter
@Getter
public class Teacher {
// @JsonValue
String name;
int age;
String address;
}
测试方法:
@Test
public void test2() throws JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
Teacher teacher = new Teacher();
teacher.setName("somnuszpli");
teacher.setAge(24);
teacher.setAddress("China");
String teacherStr = mapper.writeValueAsString(teacher);
System.out.println(teacherStr);
}
输出结果:
{"name":"somnuszpli","age":24,"address":"China"}
在Teacher类的name属性上添加@JsonValue
注解
package org.zpli.springdemo.bean;
import com.fasterxml.jackson.annotation.JsonValue;
import lombok.Getter;
import lombok.Setter;
/**
* created at 2021/6/3 3:38 下午
*
* @author somnuszpli
*/
@Setter
@Getter
public class Teacher {
@JsonValue
String name;
int age;
String address;
}
运行测试方法,输出结果为:
"somnuszpli"
Jackson的反序列化
一、Jackson反序列化过程做了什么?
对于Jackson的JSON数据格式,反序列化过程就是将JSON字符串反序列化为java 对象。
ObjectMapper mapper = new ObjectMapper();
//将JSON字符串反序列化为java对象
String jsonInString = "{\"name\":\"乔丹\",\"age\":45,\"hobbies\":[\"高尔夫球\",\"棒球\"]}";
PlayerStar jordan = mapper.readValue(jsonInString, PlayerStar.class);
System.out.println(jordan);
默认情况下,Jackson在反序列化过程中调用了哪些函数,给大家介绍一下
- 首先调用反序列化的目标类PlayerStar的无参构造函数,构造一个java对象
- 然后调用该类的成员变量的set方法,为该对象的每一个成员变量赋值。
所以默认情况下,一个Java类使用Jackson做反序列化,必须有public无参构造函数(java中不写也默认有),必须有成员变量的set方法。
二、@JsonCreator
注解
默认情况下,Jackson的反序列化过程是上面描述的那样,默认选择类的无参构造函数创建类对象并使用setter方法给属性赋值,当没有无参构造函数时会报错。除此之外,我们还可以使用@JsonCreator
注解自定义反序列化的过程,在我们自定义的反序列化函数里面,我们有更强的灵活性,可以完成更多的非规定动作。使用@JsonCreator
注解的参数前面需要加上@JsonProperty,否则会报错。一共有两种自定义反序列化渠道:
-
@JsonCreator
注解加在构造方法上 -
@JsonCreator
注解加在工厂静态方法上
使用了@JsonCreator
注解之后,将使用该注解标注的方法进行反序列化对象的构造,默认的使用无参构造函数及set方法进行反序列化的过程失效。
2.1.@JsonCreator
注解加在构造方法上
该PlayerStar对应的JSON字符串是第一小节中的jsonInString。下文的构造函数,你希望将哪些属性值赋值给java 对象的成员变量,你就使用@JsonProperty("salary")
去定义它。
package org.zpli.springdemo.bean;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.math.BigDecimal;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
/**
* created at 2021/6/3 3:14 下午
*
* @author somnuszpli
*/
public class PlayerStar {
private String name;
private Integer age;
private String[] hobbies; // 业余爱好,数组
private List<String> friends; // 朋友
private Map<String, BigDecimal> salary; // 年收入 Map
//这段是我们的核心代码,使用JsonCreator注解说明该方法是反序列化构造方法。
@JsonCreator
public PlayerStar(@JsonProperty("name") String name,
@JsonProperty("age") Integer age,
@JsonProperty("hobbies") String[] hobbies,
@JsonProperty("friends") List<String> friends,
@JsonProperty("salary") Map<String, BigDecimal> salary) {
this.name = name;
this.age = age;
this.hobbies = hobbies;
this.friends = friends;
this.salary = salary;
}
@Override
public String toString() {
return "PlayerStar{" +
"name='" + name + '\'' +
", age=" + age +
", hobbies=" + Arrays.toString(hobbies) +
", friends=" + friends +
", salary=" + salary +
'}';
}
}
我们使用第一小节中的反序列化代码,将jsonInString反序列化构造PlayerStar对象,控制台输出结果如下(对象的toString()方法输出):
PlayerStar{name='乔丹', age=45, hobbies=[高尔夫球, 棒球], friends=null, salary=null}
在 @JsonCreator
标注的构造方法里面下断点,也的确证明在java 对象反序列化构造的过程中使用的是该方法。
2.2.@JsonCreator
注解加在工厂静态方法上
除了可以将@JsonCreator
加在构造方法上,还可以使用静态工厂函数反序列化构造java对象。使用方法如下:
package org.zpli.springdemo.bean;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.math.BigDecimal;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
/**
* created at 2021/6/3 3:14 下午
*
* @author somnuszpli
*/
public class PlayerStar {
private String name;
private Integer age;
private String[] hobbies; // 业余爱好,数组
private List<String> friends; // 朋友
private Map<String, BigDecimal> salary; // 年收入 Map
@JsonCreator
public static PlayerStar createPlayer(@JsonProperty("name") String name,
@JsonProperty("age") Integer age,
@JsonProperty("hobbies") String[] hobbies,
@JsonProperty("friends") List<String> friends,
@JsonProperty("salary") Map<String, BigDecimal> salary) {
PlayerStar player = new PlayerStar(); //new 一个java对象
player.name = name; //赋值
player.age = age;
player.hobbies = hobbies;
player.friends = friends;
player.salary = salary;
return player;
}
@Override
public String toString() {
return "PlayerStar{" +
"name='" + name + '\'' +
", age=" + age +
", hobbies=" + Arrays.toString(hobbies) +
", friends=" + friends +
", salary=" + salary +
'}';
}
}
使用@JsonCreator
注解加在工厂静态方法上,可以达到一样的反序列化效果。
三、@ConstructorProperties
注解
@ConstructorProperties
注解的作用和@JsonCreator
注解起到的作用是一致的,但是它只能加在构造方法上,作为反序列化函数。但是它的语法更简洁,使用起来也更加方便,不用@JsonProperty
注解。又提供了灵活性,我们可以在构造方法反序列化过程中,针对该对象做更多的非规定操作。
package org.zpli.springdemo.bean;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.beans.ConstructorProperties;
import java.math.BigDecimal;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
/**
* created at 2021/6/3 3:14 下午
*
* @author somnuszpli
*/
public class PlayerStar {
private String name;
private Integer age;
private String[] hobbies; // 业余爱好,数组
private List<String> friends; // 朋友
private Map<String, BigDecimal> salary; // 年收入 Map
@ConstructorProperties({"name", "age","hobbies", "friends","salary"})
public PlayerStar(String name,
Integer age,
String[] hobbies,
List<String> friends,
Map<String, BigDecimal> salary) {
this.name = name;
this.age = age;
this.hobbies = hobbies;
this.friends = friends;
this.salary = salary;
}
@Override
public String toString() {
return "PlayerStar{" +
"name='" + name + '\'' +
", age=" + age +
", hobbies=" + Arrays.toString(hobbies) +
", friends=" + friends +
", salary=" + salary +
'}';
}
}
使用@ConstructorProperties
注解加在构造方法上,可以达到一样的反序列化效果。