Java 8新增了Optional
,LocalDate
等特性,而原本的jackson-databind套件由於不支援這些特性,當對含有以上特性的物件與json字串間的轉換時,會出現我們不想要的結果或錯誤,所以jackson加入了Java 8 Module等套件來支援以上特性。
例如下面是要被轉成json字串的類別Person
,其屬性中含有Java 8 的Optional
及LocalDate
class Person {
private String name;
private Optional<String> nickname; // <-- 其實這是種bad smell,不要把Optional用再class field
private LocalDate birthday;
public Person(String name, LocalDate birthday) {
this.name = name;
this.birthday= birthday;
}
// 省略getter, setter
}
使用ObjectMapper
將person
物件轉為json字串
import java.time.LocalDate;
import java.time.Month;
import java.util.Optional;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
public class Main {
public static void main(String[] args) throws JsonProcessingException {
ObjectMapper objectMapper = new ObjectMapper();
Person person = new Person("Bruce", LocalDate.of(1988, Month.APRIL, 5));
person.setNickname(Optional.of("Chief Architect"));
String jsonString = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(person);
System.out.println(jsonString);
}
}
則印出以下結果。可以看到Optional
屬性nickname
並沒有印出實際的值,LocalDate
的格式也不是簡單的年月日。
{
"name" : "Bruce",
"nickname" : {
"present" : true
},
"birthday" : {
"year" : 1988,
"month" : "APRIL",
"chronology" : {
"id" : "ISO",
"calendarType" : "iso8601"
},
"era" : "CE",
"dayOfMonth" : 5,
"dayOfWeek" : "TUESDAY",
"dayOfYear" : 96,
"leapYear" : true,
"monthValue" : 4
}
}
所以可以使用jackson的Java 8 module,在Maven的pom.xml
加入以下依賴。
<dependency>
<groupId>com.fasterxml.jackson.module</groupId>
<artifactId>jackson-module-parameter-names</artifactId>
<version>2.9.9</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jdk8</artifactId>
<version>2.9.9</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
<version>2.9.9</version>
</dependency>
然後在呼叫ObjectMapper
的registerModule(Module module)
方法來註冊Java 8相關的Module。
import java.io.IOException;
import java.time.LocalDate;
import java.time.Month;
import java.time.format.DateTimeFormatter;
import java.util.Optional;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
import com.fasterxml.jackson.datatype.jdk8.Jdk8Module;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
public class Main {
public static void main(String[] args) throws IOException {
Person person1 = new Person("Bruce", LocalDate.of(1988, Month.APRIL, 5));
person1.setNickname(Optional.of("Chief Architect"));
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.registerModule(new Jdk8Module())
.registerModule(new JavaTimeModule().addSerializer( // 設定序列化器
new StdSerializer<LocalDate>(LocalDate.class) {
private static final long serialVersionUID = 1L;
@Override
public void serialize(LocalDate value, JsonGenerator gen, SerializerProvider provider) throws IOException {
String dateString = value.format(DateTimeFormatter.ISO_DATE);
gen.writeString(dateString);
}
}).addDeserializer(LocalDate.class, new LocalDateDeserializer(DateTimeFormatter.ISO_DATE))); // 設定反序列化器
String jsonString = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(person1);
System.out.println(jsonString);
System.out.println("===================================================");
Person person2 = objectMapper.readValue(jsonString, Person.class);
System.out.println(person2);
}
}
印出結果如下
{
"name" : "Bruce",
"nickname" : "Chief Architect",
"birthday" : "1988-04-05"
}
===================================================
name=Bruce,
nickname=Optional[Chief Architect],
birthday=1988-04-05
參考:
沒有留言:
張貼留言