You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Vertx中JsonObject与POJO序列化失败问题求助

Vert.x 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 17:16:04