使用Jackson进行Java Mongo DBObject的高效POJO映射 [英] Efficient POJO mapping to/from Java Mongo DBObject using Jackson

查看:304
本文介绍了使用Jackson进行Java Mongo DBObject的高效POJO映射的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

虽然类似于使用MongoDB Java将DBObject转换为POJO驱动程序我的问题不同,因为我特别对使用Jackson进行映射感兴趣。

Although similar to Convert DBObject to a POJO using MongoDB Java Driver my question is different in that I am specifically interested in using Jackson for mapping.

我有一个我想要的对象转换为Mongo DBObject实例。我想使用Jackson JSON框架来完成这项工作。

I have an object which I want to convert to a Mongo DBObject instance. I want to use the Jackson JSON framework to do the job.

一种方法是:

DBObject dbo = (DBObject)JSON.parse(m_objectMapper.writeValueAsString(entity));

然而,根据 https://github.com/FasterXML/jackson-docs/wiki/Presentation:-Jackson-Performance 这是最糟糕的方式。所以,我正在寻找替代方案。理想情况下,我希望能够挂钩到JSON生成管道并动态填充 DBObject 实例。这是可能的,因为在我的情况下,目标是 BasicDBObject 实例,它实现了Map接口。因此,它应该很容易适应管道。

However, according to https://github.com/FasterXML/jackson-docs/wiki/Presentation:-Jackson-Performance this is the worst way to go. So, I am looking for an alternative. Ideally, I would like to be able to hook into the JSON generation pipeline and populate a DBObject instance on the fly. This is possible, because the target in my case is a BasicDBObject instance, which implements the Map interface. So, it should fit into the pipeline easily.

现在,我知道我可以使用 ObjectMapper.convertValue function然后使用 BasicDBObject 类型的映射构造函数递归地将映射转换为 BasicDBObject 实例。但是,我想知道我是否可以消除中间映射并直接创建 BasicDBObject

Now, I know I can convert an object to Map using the ObjectMapper.convertValue function and then recursively convert the map to a BasicDBObject instance using the map constructor of the BasicDBObject type. But, I want to know if I can eliminate the intermediate map and create the BasicDBObject directly.

注意,因为 BasicDBObject 本质上是一个映射,相反的转换,即从标量 DBObject 到POJO是微不足道的,应该非常有效:

Note, that because a BasicDBObject is essentially a map, the opposite conversion, namely from a scalar DBObject to a POJO is trivial and should be quite efficient:

DBObject dbo = getDBO();
Class clazz = getObjectClass();
Object pojo = m_objectMapper.convertValue(dbo, clazz);

最后,我的POJO没有任何JSON注释,我希望它保持这种方式。

Lastly, my POJO do not have any JSON annotations and I would like it to keep this way.

推荐答案

您可以使用Mixin注释来注释您的POJO和 BasicDBObject (或 DBObject ),因此注释不是问题。由于 BasicDBOject 是一个地图,你可以在put方法上使用 @JsonAnySetter

You can probably use Mixin annotations to annotate your POJO and the BasicDBObject (or DBObject), so annotations is not a problem. Since BasicDBOject is a map, you can use @JsonAnySetter on the put method.

m_objectMapper.addMixInAnnotations(YourMixIn.class, BasicDBObject.class);

public interface YourMixIn.class {
    @JsonAnySetter
    void put(String key, Object value);
}

由于我对MongoDB对象没有任何经验,所以我能想到这一切。

This is all I can come up with since I have zero experience with MongoDB Object.

更新: MixIn 基本上是杰克逊机制,在不修改所述类的情况下向类添加注释。如果您无法控制要编组的类(例如,当它来自外部jar)或者您不希望使用注释使类混乱时,这是完美的选择。

Update: MixIn are basically a Jackson mechanism to add annotation to a class without modifying said class. This is a perfect fit when you don't have control over the class you want to marshal (like when it's from an external jar) or when you don't want to clutter your classes with annotation.

在这种情况下,你说 BasicDBObject 实现了 Map 接口,所以这个类具有方法 put ,由地图界面定义。通过向该方法添加 @JsonAnySetter ,你告诉杰克逊,每当他在类内省后发现一个他不知道的属性,就可以使用该方法将属性插入到对象中。关键是属性的名称,值是,属性的​​值。

In your case here, you said that BasicDBObject implements the Map interface, so that class has the method put, as defined by the map interface. By adding @JsonAnySetter to that method, you tell Jackson that whenever he finds a property that he doesn't know after introspection of the class to use the method to insert the property to the object. The key is the name of the property and the value is, well, the value of the property.

所有这些组合使得中间地图消失,因为Jackson将直接转换为 BasicDBOject ,因为它现在知道如何从Json反序列化该类。使用该配置,您可以:

All this combined makes the intermediate map go away, since Jackson will directly convert to the BasicDBOject because it now knows how to deserialize that class from Json. With that configuration, you can do:

DBObject dbo = m_objectMapper.convertValue(pojo, BasicDBObject.class);

请注意,我没有测试过这个,因为我不使用MongoDB,所以可能会有一些松散的目的。但是,我对相似的用例使用了相同的机制,没有任何问题。 YMMV取决于班级。

Note that I haven't tested this because I don't work with MongoDB, so there might be some loose ends. However, I have used the same mechanism for similar use cases without any problem. YMMV depending on the classes.

这篇关于使用Jackson进行Java Mongo DBObject的高效POJO映射的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆