从POJO到vertx.io的JsonObject的优雅映射?

2022-09-01 13:57:11

我目前正在开发一个 vertx.io 应用程序,并希望使用提供mongo api进行数据存储。我目前在库存JsonObject类之上有一个相当笨拙的抽象,其中所有和方法都被替换为如下内容:getset

this.backingObject.get(KEY_FOR_THIS_PROPERTY);

现在一切都很好,但它不会特别好。它看起来也很脏,特别是在使用嵌套数组或对象时。例如,如果我希望仅在实际数据已知时才能够填充字段,则必须检查数组是否存在,以及它是否不创建它并将其存储在对象中。然后,我可以向列表中添加一个元素。例如:

if (this.backingObject.getJsonArray(KEY_LIST) == null) {
    this.backingObject.put(KEY_LIST, new JsonArray());
}
this.backingObject.getJsonArray(KEY_LIST).add(p.getBackingObject());

我考虑过潜在的解决方案,但并不特别喜欢其中任何一个。也就是说,我可以使用Gson或一些具有注释支持的类似库来处理加载对象以操作代码中的数据,然后使用Gson和Vertx的序列化和非序列化函数在格式之间进行转换,但这是一个非常粗糙且低效的工作流程。我也可以想出某种抽象包装器来扩展/实现vertx json库,但将所有功能传递给gson,但这似乎也有很多工作要做。(vertx to load data -> json string -> gson to parse json into pojos -> make changes -> serialize to json string -> parse with vertx and save)

有没有好的方法可以使用vertx实现更友好和可维护的序列化?


答案 1

我刚刚向Vert.x提交了一个补丁,它定义了两个新的便利函数,用于在JsonObject和Java对象实例之间进行转换,而不会出现通过中间JSON字符串表示的低效率。这将在版本 3.4 中。

// Create a JsonObject from the fields of a Java object.
// Faster than calling `new JsonObject(Json.encode(obj))`.
public static JsonObject mapFrom(Object obj)

// Instantiate a Java object from a JsonObject.
// Faster than calling `Json.decodeValue(Json.encode(jsonObject), type)`.
public <T> T mapTo(Class<T> type)

在内部,这使用,参见蒂姆·普特南的答案,以警告这种方法。代码在这里ObjectMapper#convertValue(...)


答案 2

我相信Jackson的函数不会通过String进行转换,而Vert.x无论如何都使用Jackson来管理JsonObject。ObjectMapper.convertValue(..)

JsonObject只是有一个表示值的基础映射,可以通过 访问,并在io.vertx.core.json.json中的公共实例上有一个Jackson序列化程序/反序列化程序。JsonObject.getMap()ObjectMapper

要在 Pojos 中表示的数据模型之间切换,可以使用 Jackson 进行序列化,您可以执行以下操作:JsonObject

JsonObject myVertxMsg = ... MyPojo pojo = Json.mapper.convertValue ( myVertxMsg.getMap(), MyPojo.class );

我想这比通过字符串更有效(但它只是一个猜测),我讨厌仅仅为了适应环境而改变数据类的想法,所以这取决于上下文 - 形式与性能。

要从 Pojo 转换为 ,请使用 Jackson 转换为映射,然后在 上使用构造函数:JsonObjectJsonObject

JsonObject myobj = new JsonObject ( Json.mapper.convertValue ( pojo, Map.class ));

  • 如果您在定义中隐含了嵌套的 JsonObjects 或 JsonArray 对象,则默认情况下,它们将被实例化为 Maps 和 Lists。JsonObject将在内部重新包装这些字段,当您访问指定这些类型的字段时(例如,使用getJsonArray(..)。

  • 由于 JsonObject 是自由格式的,并且您正在转换为静态类型,因此您可能会得到一些不需要的 UnrecognizedPropertyException 来处理。创建自己的 ObjectMapper,添加 vertx JsonObjectSerializer 和 JsonArraySerializer,然后进行配置更改以适应(例如在 Jackson 中)可能会很有用。DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES