Vertx中JsonObject与POJO序列化失败问题求助
我在测试Vert.x中JsonObject与POJO的映射,已添加fromJson和toJson方法并计划配置到json-mappers.properties中使用。该POJO为不可变类,使用Lombok的@Value、@Builder和@Jacksonized注解。
POJO代码
@Value @Jacksonized @Builder public class AdSystem { String version; String system; public Optional<String> getVersion() { return Optional.ofNullable(version); } public Optional<String> getSystem() { return Optional.ofNullable(system); } public JsonObject toJson() { return JsonObject.mapFrom(this); } public static AdSystem fromJson(JsonObject jsonObject) { return jsonObject.mapTo(AdSystem.class); } }
测试情况
测试发现反序列化正常,但序列化失败。测试代码如下:
@Test public void toJson_passes() { var system = new AdSystem("1", "iabtechlab"); var json = system.toJson(); assertThat(json).isEqualTo(new JsonObject().put("version", "1").put("system", "iabtechlab")); } @Test public void fromJson_passes() { var json = new JsonObject().put("version", "1").put("system", "iabtechlab"); var system = AdSystem.fromJson(json); assertThat(system).isEqualTo(new AdSystem("1", "iabtechlab")); }
失败结果
org.junit.ComparisonFailure: Expected :{"version":"1","system":"iabtechlab"} Actual :{"version":{"empty":false,"present":true},"system":{"empty":false,"present":true}}
问题原因
问题出在你重写了getVersion()和getSystem()方法,返回类型为Optional<String>。Vert.x的JsonObject.mapFrom()方法会通过反射遍历类的getter方法,将getter的返回值直接作为序列化后的字段值,因此这里把Optional对象本身序列化了,而非Optional内部的String值。
反序列化正常是因为mapTo()基于Jackson实现,Jackson会直接匹配POJO的底层String字段,忽略你自定义的getter返回的Optional类型,所以反序列化不受影响。
解决方案
方案一:将字段类型改为Optional(推荐)
去掉自定义的getter方法,让Lombok自动生成,同时把字段直接定义为Optional<String>,Jackson会自动处理Optional的序列化/反序列化:
@Value @Jacksonized @Builder public class AdSystem { Optional<String> version; Optional<String> system; public JsonObject toJson() { return JsonObject.mapFrom(this); } public static AdSystem fromJson(JsonObject jsonObject) { return jsonObject.mapTo(AdSystem.class); } }
Jackson会将非空Optional序列化为对应String值,空Optional序列化为null(可通过Jackson配置改为忽略该字段);反序列化时会自动将JSON中的null转为空Optional。
方案二:手动构建JsonObject
如果必须保留字段为String类型,可在toJson方法中手动提取Optional的值并构建JsonObject:
public JsonObject toJson() { JsonObject json = new JsonObject(); getVersion().ifPresent(v -> json.put("version", v)); getSystem().ifPresent(s -> json.put("system", s)); return json; }
这种方式能精准控制序列化后的字段内容,避免直接序列化Optional对象。
内容的提问来源于stack exchange,提问作者John Mercier

