自定义序列化与反序列化在Java中的实践
在上一篇教程中,我们探讨了如何使用@JsonSerialize#converter
和@JsonDeserialize#converter
属性。本教程将深入探讨@JsonDeserialize#using
和@JsonSerialize#using
的使用,这两个属性需要指定JsonSerializer
和JsonDeserializer
类类型。
实例分析
Java对象定义
首先,我们定义一个CurrencyRate
类,用于表示货币兑换率信息。该类包含货币对、汇率以及最后更新时间。
package com.logicbig.example;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import java.time.LocalDateTime;
public class CurrencyRate {
private String pair;
private double rate;
@JsonSerialize(using = LocalDateTimeSerializer.class)
@JsonDeserialize(using = LocalDatetimeDeserializer.class)
private LocalDateTime lastUpdated;
// 省略getter和setter方法
}
自定义序列化器
接下来,我们创建一个LocalDateTimeSerializer
类,用于将LocalDateTime
对象序列化为特定格式的字符串。
package com.logicbig.example;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import java.io.IOException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
public class LocalDateTimeSerializer extends JsonSerializer<LocalDateTime> {
static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM);
@Override
public void serialize(LocalDateTime value, JsonGenerator gen, SerializerProvider provider)
throws IOException {
try {
String s = value.format(DATE_FORMATTER);
gen.writeString(s);
} catch (DateTimeParseException e) {
System.err.println(e);
gen.writeString("");
}
}
}
自定义反序列化器
然后,我们创建一个LocalDatetimeDeserializer
类,用于将字符串反序列化为LocalDateTime
对象。
package com.logicbig.example;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import java.io.IOException;
import java.time.LocalDateTime;
import java.time.format.DateTimeParseException;
public class LocalDatetimeDeserializer extends JsonDeserializer<LocalDateTime> {
@Override
public LocalDateTime deserialize(JsonParser p, DeserializationContext ctx)
throws IOException {
String str = p.getText();
try {
return LocalDateTime.parse(str, LocalDateTimeSerializer.DATE_FORMATTER);
} catch (DateTimeParseException e) {
System.err.println(e);
return null;
}
}
}
测试主类
最后,我们编写一个测试主类ExampleMain
,演示如何将Java对象转换为JSON字符串,以及如何将JSON字符串反序列化为Java对象。
public class ExampleMain {
public static void main(String[] args) throws IOException {
System.out.println("-- Java object to JSON --");
CurrencyRate cr = new CurrencyRate();
cr.setPair("USD/JPY");
cr.setRate(109.15);
cr.setLastUpdated(LocalDateTime.now());
System.out.println("Java object: " + cr);
ObjectMapper om = new ObjectMapper();
String s2 = om.writeValueAsString(cr);
System.out.println("JSON string: " + s2);
System.out.println("-- JSON to Java object --");
CurrencyRate cr2 = om.readValue(s2, CurrencyRate.class);
System.out.println("Java Object: " + cr2);
}
}
输出结果
-- Java object to JSON --
Java object: CurrencyRate{pair='USD/JPY', rate=109.15, lastUpdated=2018-06-01T16:02:40.887586300}
JSON string: {"pair":"USD/JPY","rate":109.15,"lastUpdated":"Jun 1, 2018, 4:02:40 PM"}
-- JSON to Java object --
Java Object: CurrencyRate{pair='USD/JPY', rate=109.15, lastUpdated=2018-06-01T16:02:40}
注册自定义序列化器和反序列化器
除了在类级别使用@JsonDeserialize
和@JsonSerialize
之外,我们还可以在ObjectMapper
级别注册自定义的序列化器和反序列化器。有关详细信息,请参考这篇教程。
示例项目技术栈
- jackson-databind 2.9.5: Jackson的核心数据绑定功能,适用于核心流式API。
- JDK 10
- Maven 3.3.9