提起 jackson,在日常使用中,由于涉及到各种序列化和反序列化的处理,就不能不提 注解,了解注解的常用方式可以极大地方便我们处理序列化,今天分享一些在使用 jackson 中涉及到的注解。
目录
1.@JsonProperty - 字段命名
@JsonProperty 注解用于在序列化时按照给定的字段名命名,在反序列化时,在 json 串中的注解字段给该字段设置属性值。
下面是注解的简单示例:- package org.example;
- import com.fasterxml.jackson.annotation.JsonProperty;
- public class PersonProperty {
- @JsonProperty("first_name")
- private String firstName;
- public PersonProperty() {
- }
- public String getFirstName() {
- return firstName;
- }
- public void setFirstName(String firstName) {
- this.firstName = firstName;
- }
- }
- ---
- public static void jsonPropertyDemo() {
- ObjectMapper objectMapper = new ObjectMapper();
- PersonProperty pp = new PersonProperty();
- pp.setFirstName("Alice");
- String jsonString = null;
- try {
- jsonString = objectMapper.writeValueAsString(pp);
- System.out.println("json property: " + jsonString);
- } catch (Exception e) {
- e.printStackTrace();
- }
- try {
- PersonProperty pp1 = objectMapper.readValue(jsonString, PersonProperty.class);
- System.out.println(pp1.getFirstName());
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- ---
复制代码 2.@JsonPropertyOrder - 字段序列化顺序
@JsonPropertyOrder加在类上,用以规定数据序列化时字段出现的顺序。- package org.example;
- import com.fasterxml.jackson.annotation.JsonPropertyOrder;
- // {"name":"Bob","id":"111","age":25,"phone":"12345678910"}
- @JsonPropertyOrder({"name", "id", "age", "phone"})
- // 没有定义顺序,就按照字典序排列,{"age":25,"id":"111","name":"Bob","phone":"12345678910"}
- // @JsonPropertyOrder(alphabetic = true)
- public class PersonPropertyOrder {
- private String id;
- private String name;
- private int age;
- private String phone;
- public PersonPropertyOrder() {
- }
- public String getId() {
- return id;
- }
- public void setId(String id) {
- this.id = id;
- }
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- public int getAge() {
- return age;
- }
- public void setAge(int age) {
- this.age = age;
- }
- public String getPhone() {
- return phone;
- }
- public void setPhone(String phone) {
- this.phone = phone;
- }
- }
- ---
- public static void jsonPropertyOrder() {
- ObjectMapper objectMapper = new ObjectMapper();
- PersonPropertyOrder ppo = new PersonPropertyOrder();
- ppo.setAge(25);
- ppo.setId("111");
- ppo.setName("Bob");
- ppo.setPhone("12345678910");
- String jsonString = null;
- try {
- jsonString = objectMapper.writeValueAsString(ppo);
- System.out.println("json property: " + jsonString);
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- ---
复制代码 3.@JsonAlias - 字段别名,反序列化
在数据反序列化时,通过 @JsonAlias 注解来设置字段的值,只要是 alias中的和字段本身都可以正常反序列化。- package org.example;
- import com.fasterxml.jackson.annotation.JsonAlias;
- public class PersonAlias {
- @JsonAlias({"firstName", "personName"})
- private String name;
- public PersonAlias() {
- }
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- }
- ---
- public static void jsonAlias() {
- String jsonString1 = "{"name":"Bob"}";
- String jsonString2 = "{"firstName":"Bob"}";
- String jsonString3 = "{"personName":"Bob"}";
- ObjectMapper objectMapper = new ObjectMapper();
- try {
- PersonAlias p1 = objectMapper.readValue(jsonString1, PersonAlias.class);
- PersonAlias p2 = objectMapper.readValue(jsonString2, PersonAlias.class);
- PersonAlias p3 = objectMapper.readValue(jsonString3, PersonAlias.class);
- System.out.printf("p1: %s, p2: %s, p3: %s", p1.getName(),p2.getName(), p3.getName());
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- ---
复制代码 4.@JsonIgnore -序列化时忽略字段
@JsonIgnore 加在字段上,用以在序列化时,忽略其,在反序列化时,仅赋值null。- package org.example;
- import com.fasterxml.jackson.annotation.JsonIgnore;
- public class PersonIgnore {
- private String name;
- @JsonIgnore // 不将其序列化,忽略该字段
- private String[] hobbies;
- public PersonIgnore() {
- }
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- public String[] getHobbies() {
- return hobbies;
- }
- public void setHobbies(String[] hobbies) {
- this.hobbies = hobbies;
- }
- }
- ---
- public static void jsonIgnore() {
- ObjectMapper objectMapper = new ObjectMapper();
- String jsonString = null;
- try {
- PersonIgnore pi = new PersonIgnore();
- pi.setName("Cathy");
- pi.setHobbies(null);
- jsonString = objectMapper.writeValueAsString(pi);
- System.out.println(jsonString);
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- ---
复制代码 5.@JsonIgnoreProperties - 序列化时忽略某些字段
@JsonIgnoreProperties 加在类上,用于在序列化时,忽略给定的某些字段。- package org.example;
- import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
- @JsonIgnoreProperties({"age"})
- public class PersonIgnoreProperties {
- private String name = "Alice";
- private int age;
- public PersonIgnoreProperties() {
- }
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- public int getAge() {
- return age;
- }
- public void setAge(int age) {
- this.age = age;
- }
- }
- ---
- public static void jsonIgnoreProperties() {
- ObjectMapper objectMapper = new ObjectMapper();
- PersonIgnoreProperties pip = new PersonIgnoreProperties();
- pip.setName("Bob");
- pip.setAge(18);
- try {
- String jsonString = objectMapper.writeValueAsString(pip);
- System.out.println(jsonString);
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- ---
复制代码 6.@JsonInclude - 序列化时作用于满足条件的
@JsonInclude可以加在类上,也可以加在字段上。该注解表示满足某些条件(
NON_NULL,
NON_ABSENT,
NON_EMPTY,
NON_DEFAULT,
等)的才能序列化,e.g.如果加在类上,表示只要对象有null 就忽略该对象,加在字段上,如果字段是null,则忽略该字段。- package org.example;
- import com.fasterxml.jackson.annotation.JsonInclude;
- @JsonInclude(JsonInclude.Include.NON_NULL)
- public class PersonInclude {
- private int id;
- private String name;
- @JsonInclude(JsonInclude.Include.NON_NULL)
- private String[] hobbies;
- public PersonInclude() {
- }
- 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;
- }
- public String[] getHobbies() {
- return hobbies;
- }
- public void setHobbies(String[] hobbies) {
- this.hobbies = hobbies;
- }
- }
- ---
- public static void jsonInclude() {
- ObjectMapper objectMapper = new ObjectMapper();
- PersonInclude pi = new PersonInclude();
- pi.setName("Cathy");
- pi.setId(1111);
- try {
- String jsonString = objectMapper.writeValueAsString(pi);
- System.out.println(jsonString);
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- ---
复制代码 7.@JsonFormat - 设置格式,如日期时间等
用于设置时间格式,或者是数字,或者是日期格式。- package org.example;
- import com.fasterxml.jackson.annotation.JsonFormat;
- import java.time.LocalDate;
- import java.util.Date;
- public class PersonFormat {
- @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd hh:mm:ss", timezone = "GMT+8")
- private Date birthDate;
- public PersonFormat() {
- }
- public Date getBirthDate() {
- return birthDate;
- }
- public void setBirthDate(Date birthDate) {
- this.birthDate = birthDate;
- }
- }
- ---
- public static void jsonFormat() {
- ObjectMapper objectMapper = new ObjectMapper();
- PersonFormat pf = new PersonFormat();
- pf.setBirthDate(new Date());
- try {
- String jsonString = objectMapper.writeValueAsString(pf);
- System.out.println(jsonString);
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- ---
复制代码 8.@JacksonInject - 反序列化时注入到 java 对象
该注解用于在数据反序列化时将其他字段注入进 Java对象。- package org.example;
- import com.fasterxml.jackson.annotation.JacksonInject;
- import java.time.LocalDate;
- import java.time.LocalDateTime;
- public class PersonInject {
- private String name;
-
- private int age;
-
- @JacksonInject("responseTime")
- private LocalDateTime responseTime;
- public PersonInject() {
- }
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- public int getAge() {
- return age;
- }
- public void setAge(int age) {
- this.age = age;
- }
- public LocalDateTime getResponseTime() {
- return responseTime;
- }
- public void setResponseTime(LocalDateTime responseTime) {
- this.responseTime = responseTime;
- }
- }
- ---
- public static void jsonInject() {
- InjectableValues.Std iv = new InjectableValues.Std();
- ObjectMapper objectMapper = new ObjectMapper();
- iv.addValue("responseTime", LocalDateTime.now());
- //将JSON字符串反序列化为java对象
- String jsonString = "{"name":"Alice","age":23}";
- objectMapper.setInjectableValues(iv);
- try {
- PersonInject pi = objectMapper.readValue(jsonString, PersonInject.class);
- System.out.println(pi.getResponseTime());
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- ---
复制代码 9.@JsonCreator && @ConstructorProperties - 反序列化时采用的构造方法
@JsonCreator 用于在json数据反序列化到实例对象时采用哪个构造方法,同时搭配 @JsonProperty 注解用于相关属性的。- package org.example;
- import com.fasterxml.jackson.annotation.JsonCreator;
- import com.fasterxml.jackson.annotation.JsonProperty;
- import com.fasterxml.jackson.databind.ObjectMapper;
- public class PersonCreator {
- private String name;
- private int age;
- // 构造方法1
- public PersonCreator(String name) {
- this.name = name;
- }
- // 构造方法2
- @JsonCreator // 用于反序列化时的处理
- public PersonCreator(@JsonProperty("username") String name,
- @JsonProperty("age") int age) {
- this.name = name;
- this.age = age;
- }
- @Override
- public String toString() {
- return "Test{" +
- "name='" + name + ''' +
- ", age='" + age + ''' +
- '}';
- }
- public static void main(String[] args) throws Exception {
- String jsonString = "{"username": "Alice", "age": 18}"; // username -> name
- ObjectMapper objectMapper = new ObjectMapper();
- try {
- PersonCreator pc = objectMapper.readValue(jsonString, PersonCreator.class);
- System.out.println(pc);
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- }
复制代码 @ConstructorProperties 也用于构造方法,但相比 @JsonCreator 的使用要简单,可以认为 @ConstructorProperties = @JsonCreator + @JsonProperty。- package org.example;
- import com.fasterxml.jackson.databind.ObjectMapper;
- import java.beans.ConstructorProperties;
- public class PersonConstructorProperties {
- private String username;
- private int age;
- public PersonConstructorProperties(String username) {
- this.username = username;
- }
- @ConstructorProperties({"name", "age"})
- public PersonConstructorProperties(String username, int age) {
- System.out.println("全参构造函数...");
- this.username = username;
- this.age = age;
- }
- @Override
- public String toString() {
- return "Test{" +
- "username='" + username + ''' +
- ", age='" + age + ''' +
- '}';
- }
- public static void main(String[] args) {
- String jsonString = "{"name": "Bob", "age": 29}";
- ObjectMapper objectMapper = new ObjectMapper();
- try {
- PersonConstructorProperties pcp = objectMapper.readValue(jsonString, PersonConstructorProperties.class);
- System.out.println(pcp);
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- }
复制代码 10.@JsonSerialize && @JsonDeserialize - 自定义序列化方法
这两个注解用于实现自定义的序列化和反序列化的处理,比如我们有个需求,需要将小数的某个字段规定精确位数,为空时输出空字符串。
@JsonSerialize- package org.example;
- import com.fasterxml.jackson.core.JsonGenerator;
- import com.fasterxml.jackson.databind.JsonSerializer;
- import com.fasterxml.jackson.databind.SerializerProvider;
- import com.fasterxml.jackson.databind.annotation.JsonSerialize;
- import java.io.IOException;
- import java.math.RoundingMode;
- import java.text.DecimalFormat;
- public class PersonSerialize {
- @JsonSerialize(using = CustomDoubleSerialize.class, nullsUsing = NullNumberSerialize.class)
- private Double model;
- @JsonSerialize(nullsUsing = NullNumberSerialize.class)
- private Double business;
- private String name;
- public PersonSerialize() {
- }
- public Double getModel() {
- return model;
- }
- public void setModel(Double model) {
- this.model = model;
- }
- public Double getBusiness() {
- return business;
- }
- public void setBusiness(Double business) {
- this.business = business;
- }
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- }
- /**
- * Double保留4位小数,输出string
- */
- class CustomDoubleSerialize extends JsonSerializer<Double> {
- private static final DecimalFormat df = new DecimalFormat("#.####");
- @Override
- public void serialize(Double value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
- df.setRoundingMode(RoundingMode.HALF_UP); // 4
- gen.writeString(df.format(value));
- }
- }
- /**
- * 任意类型null值,改为空字符串输出
- */
- class NullNumberSerialize extends JsonSerializer<Object> {
- @Override
- public void serialize(Object value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
- gen.writeString("");
- }
- }
- ---
- public static void jsonSerialize() {
- ObjectMapper objectMapper = new ObjectMapper();
- PersonSerialize ps = new PersonSerialize();
- ps.setName("Alice");
- ps.setModel(1.2345678);
- try {
- String jsonString = objectMapper.writeValueAsString(ps);
- System.out.println(jsonString); // {"model":"1.2346","business":"","name":"Alice"}
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- ---
复制代码 @JsonDeserialize- package org.example;
- import com.fasterxml.jackson.core.JsonGenerator;
- import com.fasterxml.jackson.core.JsonParser;
- import com.fasterxml.jackson.databind.DeserializationContext;
- import com.fasterxml.jackson.databind.JsonDeserializer;
- import com.fasterxml.jackson.databind.JsonSerializer;
- import com.fasterxml.jackson.databind.SerializerProvider;
- import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
- import com.fasterxml.jackson.databind.annotation.JsonSerialize;
- import java.io.IOException;
- import java.time.LocalDateTime;
- import java.time.format.DateTimeFormatter;
- import java.time.format.FormatStyle;
- public class PersonDeserialize {
- @JsonSerialize(using = LocalDatetimeSerialize.class)
- @JsonDeserialize(using = LocalDatetimeDeserialize.class)
- private LocalDateTime birthDate;
- private String name;
- public PersonDeserialize() {
- }
- public LocalDateTime getBirthDate() {
- return birthDate;
- }
- public void setBirthDate(LocalDateTime birthDate) {
- this.birthDate = birthDate;
- }
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- }
- class LocalDatetimeSerialize extends JsonSerializer<LocalDateTime> {
- static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM);
- @Override
- public void serialize(LocalDateTime value, JsonGenerator gen, SerializerProvider provider) throws IOException {
- String str = value.format(DATE_FORMATTER);
- gen.writeString(str);
- }
- }
- class LocalDatetimeDeserialize extends JsonDeserializer<LocalDateTime> {
- @Override
- public LocalDateTime deserialize(JsonParser p, DeserializationContext ctx) throws IOException {
- String str = p.getText();
- return LocalDateTime.parse(str, LocalDatetimeSerialize.DATE_FORMATTER);
- }
- }
- ---
- public static void jsonDeserialize() {
- ObjectMapper objectMapper = new ObjectMapper();
- PersonDeserialize pd = new PersonDeserialize();
- pd.setName("Dav");
- pd.setBirthDate(LocalDateTime.of(2000, 12, 5, 0, 0));
- String jsonString = null;
- // serialize
- try {
- jsonString = objectMapper.writeValueAsString(pd);
- System.out.println(jsonString); // {"birthDate":"2000年12月5日 00:00:00","name":"Dav"}
- } catch (Exception e) {
- e.printStackTrace();
- }
- // deserialize
- try {
- PersonDeserialize pd1 = objectMapper.readValue(jsonString, PersonDeserialize.class);
- // person -> name: Dav, birthdate: 2000-12-05T00:00
- System.out.printf("person -> name: %s, birthdate: %s\n", pd1.getName(), pd1.getBirthDate());
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- ---
复制代码 11.@JsonAnyGetter && @JsonANySetter - 序列化对map字段的处理
这两个注解用于在序列化和反序列化时 map 结构的处理,具体说来:
- @JsonAnyGetter,加在 getField() 上,用于序列化时将此map字段的键值对移至json中的键值对
- @JsonAnySetter,加在字段上或者 setField() 都可以,加一个即可,用于反序列化时构造类实例,设置类实例属性,将json中的非明确定义的键值对都设置到map结构的字段中
- package org.example;
- import com.fasterxml.jackson.annotation.JsonAnyGetter;
- import com.fasterxml.jackson.annotation.JsonAnySetter;
- import java.util.HashMap;
- import java.util.Map;
- public class PersonGetAndSet {
- private String username;
- private String pwd;
- private int age;
- // @JsonAnySetter // 加方法或者属性都可以,但1个即可
- private Map<String, String> map;
- public PersonGetAndSet() {
- this.map = new HashMap<>();
- }
- public String getUsername() {
- return username;
- }
- public void setUsername(String username) {
- this.username = username;
- }
- public String getPwd() {
- return pwd;
- }
- public void setPwd(String pwd) {
- this.pwd = pwd;
- }
- public int getAge() {
- return age;
- }
- public void setAge(int age) {
- this.age = age;
- }
- @JsonAnyGetter // serialize, {"username":"Ada","pwd":"123456","age":26,"key1":"val1","key2":"val2"}
- public Map<String, String> getMap() {
- return map;
- }
- @JsonAnySetter // deserialize, pwd: 123456, age: 26, map: {key1=val1, key2=val2}
- public void setMap(String key, String value) {
- this.map.put(key, value);
- }
- }
- ---
- public static void jsonGetterAndSetter() {
- PersonGetAndSet pgs = new PersonGetAndSet();
- pgs.setUsername("Ada");
- pgs.setAge(26);
- pgs.setPwd("123456");
- pgs.setMap("key1", "val1");
- pgs.setMap("key2", "val2");
- ObjectMapper objectMapper = new ObjectMapper();
- String jsonString = null;
- try {
- jsonString = objectMapper.writeValueAsString(pgs);
- System.out.println(jsonString);
- } catch (Exception e) {
- e.printStackTrace();
- }
- try {
- PersonGetAndSet pgs1 = objectMapper.readValue(jsonString, PersonGetAndSet.class);
- System.out.printf("person -> username: %s, pwd: %s, age: %d, map: %s\n", pgs1.getUsername(), pgs1.getPwd(), pgs1.getAge(), pgs1.getMap());
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- ---
复制代码 12.@JsonNaming - 序列化时输出格式
@JsonNaming 加在类上,用以规范序列化时输出的字段键值的形式,主要有以下格式:
- SnakeCaseStrategy, 蛇形体, 如 first_name
- UpperCamelCaseStrategy, 大写驼峰体,如 FirstName
- LowerCaseStratey, 小写连体,如 firstname
- LowerDotCaseStratey, 小写点分,如 first.name
- package org.example;
- import com.fasterxml.jackson.databind.ObjectMapper;
- import com.fasterxml.jackson.databind.PropertyNamingStrategy;
- import com.fasterxml.jackson.databind.annotation.JsonNaming;
- //@JsonNaming(value = PropertyNamingStrategy.SnakeCaseStrategy.class) // 蛇形体:{"first_name":"Matt","second_name":"Damon"}
- //@JsonNaming(value = PropertyNamingStrategy.UpperCamelCaseStrategy.class) // {"FirstName":"Matt","SecondName":"Damon"}
- //@JsonNaming(value = PropertyNamingStrategy.LowerCaseStrategy.class) // {"firstname":"Matt","secondname":"Damon"}
- @JsonNaming(value = PropertyNamingStrategy.LowerDotCaseStrategy.class) // {"first.name":"Matt","second.name":"Damon"}
- public class PersonNaming {
- private String firstName;
- private String secondName;
- public PersonNaming() {
- }
- public PersonNaming(String firstName, String secondName) {
- this.firstName = firstName;
- this.secondName = secondName;
- }
- public String getFirstName() {
- return firstName;
- }
- public void setFirstName(String firstName) {
- this.firstName = firstName;
- }
- public String getSecondName() {
- return secondName;
- }
- public void setSecondName(String secondName) {
- this.secondName = secondName;
- }
- public static void main(String[] args) {
- PersonNaming pn = new PersonNaming();
- pn.setFirstName("Matt");
- pn.setSecondName("Damon");
- ObjectMapper objectMapper = new ObjectMapper();
- try {
- String jsonString = objectMapper.writeValueAsString(pn);
- System.out.println(jsonString);
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- }
复制代码 13.staic 和 transient 字段
如果字段属性中有这两个修饰符,则在序列化处理时忽略相关字段。
参考:
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |