本文主要讲解全由官方主导维护的三个模块,是实际应用中使用得最广泛的、和我们工作密切相关的模块们:
- jackson-module-parameter-names
- jackson-datatype-jdk8
- jackson-datatype-jsr310
jackson-module-parameter-names
<dependency>
<groupId>com.fasterxml.jackson.module</groupId>
<artifactId>jackson-module-parameter-names</artifactId>
<version>${jackson.version}</version>
</dependency>
@Test
public void fun1() throws JsonProcessingException {
JsonMapper mapper = new JsonMapper();
String jsonStr = "{\"name\":\"YourBatman\",\"age\":18}";
Person person = mapper.readValue(jsonStr, Person.class);
System.out.println(person);
}
@Getter
@Setter
@ToString
public class Person {
private String name;
private Integer age;
public Person(String name, Integer age) {
this.name = name;
this.age = age;
}
}
运行报错如下
com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `com.youtbatman.java...
这个报错很容易理解,因为没有找到合适的构造器来创建Person,怎么破?可以这样做
@JsonCreator
public Person(@JsonProperty("name") String name,@JsonProperty("age") Integer age) {
this.name = name;
this.age = age;
}
再次运行正常输出
Person(name=YourBatman, age=18)
在使用该注解时有如下注意事项:
- @JsonProperty是必须的,且value属性也是必须填写的
- 实验证明value属性写得不一样也没关系,但仍建议保持和JSON串的一致
- @JsonProperty最好给构造器的每个参数都标记,上(否则容易拋错),标记好@JsonP roperty后的构造器,@JsonCreator 并不是必须的了,但也建议显示的标注上
可以看到使用这种方式处理还是较为繁琐:需要使用大量的注解来标注才行。那么,jackson-module-parameter-names就拯救了这一切,让Jackson的处理得更加的优雅
// 给JsonMapper显示注册上此模块
mapper.registerModule(new ParameterNamesModule());
// POJO无需给与任何注册
public Person(String name, Integer age) {
this.name = name;
this.age = age;
}
再次运行,程序正常输出
Person(name=YourBatman, age=18)
注意:如果你这么来用没有效果(依旧报错),请检查你是否基于Java8+编译,并且确认是否开启了-parameters这个编译参数
jackson-datatype-jdk8
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jdk8</artifactId>
<version>${jackson.version}</version>
</dependency>
顾名思义,它提供了对Java8新类型的-些支持,如: Optional/0pt ionalInt/0pt ionalLong/0pt ionalDouble等以及St ream/ IntStream/LongSt ream/DoubleStream等.
@Test
public void fun1() throws JsonProcessingException {
JsonMapper mapper = new JsonMapper();
System.out.println("注册JDK8模块前:");
mapper.writeValueAsString(OptionalInt.of(1));
mapper.writeValueAsString(Optional.of("YourBatman"));
mapper.writeValueAsString(IntStream.of(1,2,3));
mapper.writeValueAsString(Stream.of("1","2","3"));
}
注册JDK8模块前:
{"asInt":1,"present":true}
{"present":true}
{"parallel":false}
{"parallel":false}
注册上jackson-datatype-jdk8模块后
mapper.registerModule(new Jdk8Module())
再次运行程序输出为:
注册JDK8模块后:
"YourBatman"
[1,2,3]
["1","2","3"]
jackson-datatype-jsr310
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
<version>${jackson.version}</version>
</dependency>
而该模块JSR310支持到了时间类型的序列化、反序列化,让处理这些类型起来都变得更加的优雅。
@Test
public void fun1() throws JsonProcessingException {
JsonMapper mapper = new JsonMapper();
System.out.println(mapper.writeValueAsString(LocalDateTime.now()));
System.out.println(mapper.writeValueAsString(LocalDate.now()));
System.out.println(mapper.writeValueAsString(LocalTime.now()));
System.out.println(mapper.writeValueAsString(Instant.now()));
}
{"year":2021,"month":"MARCH","nano":398000000,"monthValue":3,"dayOfMonth":12,"hour":23,"minute":44,"second":37,"dayOfYear":71,"dayOfWeek":"FRIDAY","chronology":{"id":"ISO","calendarType":"iso8601"}}
{"year":2021,"month":"MARCH","monthValue":3,"dayOfMonth":12,"chronology":{"id":"ISO","calendarType":"iso8601"},"era":"CE","dayOfYear":71,"dayOfWeek":"FRIDAY","leapYear":false}
{"hour":23,"minute":44,"second":37,"nano":528000000}
{"epochSecond":1615563877,"nano":530000000}
注册jackson-datatype-jsr310模块后
mapper.registerModule(new JavaTimeModule());
运行结果如下
[2021,3,12,23,45,11,818000000]
[2021,3,12]
[23,45,11,849000000]
1615563911.849000000
网友评论