使用Jackson进行Java Mongo DBObject的高效POJO映射

mar*_*ark 19 java mongodb jackson mongo-jackson-mapper

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

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

一种方法是:

DBObject dbo = (DBObject)JSON.parse(m_objectMapper.writeValueAsString(entity));
Run Code Online (Sandbox Code Playgroud)

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

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

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

DBObject dbo = getDBO();
Class clazz = getObjectClass();
Object pojo = m_objectMapper.convertValue(dbo, clazz);
Run Code Online (Sandbox Code Playgroud)

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

Pas*_*nas 11

您可以使用Mixin注释来注释您的POJO和BasicDBObject(或DBObject),因此注释不是问题.由于BasicDBOject是地图,您可以使用@JsonAnySetterput方法.

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

public interface YourMixIn.class {
    @JsonAnySetter
    void put(String key, Object value);
}
Run Code Online (Sandbox Code Playgroud)

这是我能想到的全部因为我没有使用MongoDB Object的经验.

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

在这种情况下,您说BasicDBObject实现了Map接口,因此该类具有putmap接口定义的方法.通过将@JsonAnySetter添加到该方法,您可以告诉Jackson,每当他在类内省后发现他不知道的属性时,使用该方法将属性插入到对象中.关键是属性的名称,值是属性的值.

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

DBObject dbo = m_objectMapper.convertValue(pojo, BasicDBObject.class);
Run Code Online (Sandbox Code Playgroud)

请注意,我没有对此进行测试,因为我不使用MongoDB,因此可能会有一些松散的结果.但是,我对相似的用例使用了相同的机制,没有任何问题.YMMV取决于班级.

  • 显然,我们不需要任何mixins和注释.Jackson可以将对象转换为相应的BasicDBObject!看起来它只是检查给定对象是否是一个地图,如果是,则继续填充目标将其视为地图. (2认同)