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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/32042938/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 11:58:23  来源:igfitidea点击:

Elegant mapping from POJOs to vertx.io's JsonObject?

javajsonvert.x

提问by grdaneault

I am currently working on a vertx.ioapplication and wanted to use the provide mongo api for data storage. I currently have a rather clunky abstraction on top of the stock JsonObject classes where all getand setmethods are replaced with things like:

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

this.backingObject.get(KEY_FOR_THIS_PROPERTY);

This is all well and good for now, but it won't scale particularly well. it also seems dirty, specifically when using nested arrays or objects. For example, if I want to be able to fill fields only when actual data is known, I have to check if the array exists, and if it doesn't create it and store it in the object. Then I can add an element to the list. For example:

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

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

I have thought about potential solutions but don't particularly like any of them. Namely, I coulduse Gson or some similar library with annotation support to handle loading the object for the purposes of manipulating the data in my code, and then using the serialize and unserialize function of both Gson and Vertx to convert between the formats (vertx to load data -> json string -> gson to parse json into pojos -> make changes -> serialize to json string -> parse with vertx and save)but that's a really gross and inefficient workflow. I could also probably come up with some sort of abstract wrapper that extends/implements the vertx json library but passes all the functionality through to gson, but that also seems like a lot of work.

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

Is there any good way to achieve more friendly and maintainable serialization using vertx?

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

采纳答案by Luke Hutchison

I just submitted a patch to Vert.x that defines two new convenience functions for converting between JsonObject and Java object instances without the inefficiency of going through an intermediate JSON string representation. This will be in version 3.4.

我刚刚向 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)

Internally this uses ObjectMapper#convertValue(...), see Tim Putnam's answer for caveats of this approach. The code is here.

这在内部使用ObjectMapper#convertValue(...),请参阅 Tim Putnam's answer 以了解此方法的注意事项。代码在这里

回答by Will

Not sure if I've understood you correctly, but it sounds like you're trying to find a simple way of converting POJOs to JsonObject?

不确定我是否理解正确,但听起来您正在尝试找到一种将 POJO 转换为 JsonObject 的简单方法?

So, we have lots of pojos that we send over the EventBusas JsonObjects

所以,我们有很多的POJO,我们送过来的EventBus作为JsonObject小号

I've found the easiest way is to use the vert.xJsonclass which has loads of helper methods to convert to / from JsonStrings

我发现最简单的方法是使用vert.xJson具有大量辅助方法的类来转换为/从JsonStrings

JsonObject jsonObject = new JsonObject(Json.encode(myPojo));

Sometimes you need to add some custom (de)serializers, but we always stick with Hymanson- that is what Vert.xis using so they work out of the box.

有时您需要添加一些自定义(反)序列化器,但我们始终坚持使用Hymanson- 这Vert.x就是使用的方法,因此它们开箱即用。

What we actually do, is provide an interface like the following:

我们实际做的是提供一个如下所示的接口:

public JsonObjectSerializable {
    public JsonObject toJson();
}

And all our pojos that need to be sent over the EventBushave to implement this interface.

我们所有需要发送的 pojoEventBus都必须实现这个接口。

Then our EventBussending code looks something like (simplified):

然后我们的EventBus发送代码看起来像(简化):

public <T extends JsonObjectSerializable> Response<T> dispatch(T eventPayload);

Also, as we generally don't unit test Pojos, adding this interfaceencourages the developers to unit test their conversion.

此外,由于我们通常不对 Pojos 进行单元测试,因此添加这会interface鼓励开发人员对他们的转换进行单元测试。

Hope this helps,

希望这可以帮助,

Will

将要

回答by Tim Putnam

I believe Hymanson's ObjectMapper.convertValue(..)functions don't convert via String, and Vert.x is using Hymanson for managing JsonObject anyway.

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

JsonObjectjust has an underlying map representing the values, accessible via JsonObject.getMap(), and a Hymanson serializer/deserializer on the public ObjectMapperinstance in io.vertx.core.json.Json.

JsonObject只是有一个表示值的底层映射,可通过JsonObject.getMap()ObjectMapperio.vertx.core.json.Json 中公共实例上的 Hymanson 序列化器/反序列化器访问。

To switch between JsonObjectand a data model expressed in Pojos serializable with Hymanson, you can do:

JsonObject在 Pojos 和 Hymanson 可序列化的数据模型之间切换,您可以执行以下操作:

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

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

I would guess this is more efficient than going via a String (but its just a guess), and I hate the idea of altering the data class just to suit the environment, so it depends on the context - form vs performance.

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

To convert from Pojo to JsonObject, convert to a map with Hymanson and then use the constructor on JsonObject:

要从 PojoJsonObject转换为 ,请使用 Hymanson 转换为映射,然后使用 on 的构造函数JsonObject

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

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

  • If you have implied nested JsonObjects or JsonArray objects in your definition, they will get instantiated as Maps and Lists by default. JsonObject will internally re-wrap these when you access fields specifying those types (e.g. with getJsonArray(..).

  • Because JsonObject is freeform and you're converting to a static type, you may get some unwanted UnrecognizedPropertyException to deal with. It may be useful to create your own ObjectMapper, add the vertx JsonObjectSerializer and JsonArraySerializer, and then make configuration changes to suit (such as DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIESin Hymanson).

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

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

回答by fengbugou

Try this:

尝试这个:

io.vertx.core.json.Json.mapper.convertValue(json.getMap(), cls)

回答by Daniel Gerson

I think that using Gson as you described is the best possible solution at the current time.

我认为使用您描述的 Gson 是目前最好的解决方案。

While I agree that if a protocol layer was included in Vert.x it would indeed be first prize, using Gson keeps your server internals pretty organised and is unlikely to be the performance bottleneck.

虽然我同意如果 Vert.x 中包含协议层,它确实会是一等奖,但使用 Gson 可以使您的服务器内部结构井井有条,并且不太可能成为性能瓶颈。

When and only when this strategy becomes the performance bottleneck have you reached the point to engineer a better solution. Anything before that is premature optimisation.

当且仅当此策略成为性能瓶颈时,您才能设计出更好的解决方案。在此之前的任何事情都是过早的优化。

My two cents.

我的两分钱。

回答by imaya

You can try:

你可以试试:

new JsonObject().mapFrom(object)