ChronicleWire实体可选字段使用报错,应如何正确实现?
问题原因说明
- 直接声明可空
Marshallable类型字段报错:2.22ae6版本ChronicleWire默认自动生成的序列化逻辑不会对Marshallable类型字段做空值检查,会直接调用该字段的序列化方法,空值触发NPE。 - 使用
java.util.Optional报错:该版本原生不支持JDK Optional作为字段类型,序列化器仅支持Marshallable实现类、字符串、装箱基础类型三类字段。 - 自定义OptionalValue报错:存在三个问题:
- write方法中空值写入方法拼写错误,把
null()写为了nu11()(数字1替代了字母l) - Lombok的
@NoArgsConstructor(staticName = "empty")会将无参构造器设为私有,序列化反射实例化时找不到公共无参构造,转而尝试查找String参数构造器失败 - 反序列化逻辑错误,非空值读取时未先实例化泛型对象,直接为null的value属性赋值
- write方法中空值写入方法拼写错误,把
修复方案
方案1:直接重写实体的序列化/反序列化方法(最简方案)
不需要额外封装可选类型,直接在实体类中手动处理可空字段即可:
public class Foo extends SelfDescribingMarshallable { private String name; private Baz baz; @Override public void writeMarshallable(@NotNull WireOut wire) { wire.write("name").text(name); if (baz == null) { wire.write("baz").null(); } else { wire.write("baz").marshallable(baz); } } @Override public void readMarshallable(@NotNull WireIn wire) { this.name = wire.read("name").text(); var bazVal = wire.read("baz"); if (!bazVal.isNull()) { this.baz = new Baz(); bazVal.marshallable(this.baz); } else { this.baz = null; } } }
方案2:修复自定义OptionalValue实现
如果需要通用可选类型封装,修复原有代码的问题即可:
import lombok.AllArgsConstructor; import lombok.NoArgsConstructor; import net.openhft.chronicle.core.util.ObjectUtils; import net.openhft.chronicle.wire.Marshallable; import net.openhft.chronicle.wire.WireIn; import net.openhft.chronicle.wire.WireOut; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.lang.reflect.ParameterizedType; @AllArgsConstructor(staticName = "of") @NoArgsConstructor public class OptionalValue<T extends Marshallable> implements Marshallable { @Nullable private T value; @Override public void readMarshallable(@NotNull WireIn wire) { var val = wire.read("value"); if (!val.isNull()) { Class<T> clazz = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0]; value = ObjectUtils.newInstance(clazz); val.marshallable(value); } else { value = null; } } @Override public void writeMarshallable(@NotNull WireOut wire) { if (value == null) { wire.write("value").null(); } else { wire.write("value").marshallable(value); } } public boolean isEmpty() { return value == null; } public T get() { return value; } public static <T extends Marshallable> OptionalValue<T> empty() { return new OptionalValue<>(); } }
内容的提问来源于stack exchange,提问作者rvit34
相关产品推荐
相关产品推荐

