有没有办法自动创建Mongo编解码器?

我愿意将我的代码从mongojack迁移到支持新的异步mongo驱动程序的代码。 然而,我发现新的编码/解码方式是通过Codec ,我不认为自己为模型中的每个类编写了一个Codec 。 这就是为什么我宁愿写一个给定类创建Codec 。 但是我不知道怎么样,也不知道是否已经有一些努力试图达到同样的目的。 是否有一些libs可以实现我想要的? 如果没有,实现它的最佳方法是什么。

(我知道我应该在那里的某处使用CodecProvider ,但我仍然不知道从哪里开始)

是的,如果您使用jackson,您可以使用https://github.com/ylemoigne/mongo-jackson-codec中的mongo-jackson-codec,它将自动为您处理。

好吧,我找不到任何指向我需要的方向,所以我开始自己的。 它可以自动创建编解码器,而无需使用Document或DBObject等中间表示。 它使用Annotation Processing在编译时创建它们。

https://github.com/caeus/vertigo

希望它适用于具有相同需求的任何其他人。

以下是我们如何解决这个问题(最终结果是Lombok,Jackson和MongoDB之间的超级流畅):

提供者:

 public class JacksonCodecProvider implements CodecProvider { private final ObjectMapper objectMapper; public JacksonCodecProvider(final ObjectMapper bsonObjectMapper) { this.objectMapper = bsonObjectMapper; } @Override public  Codec get(final Class type, final CodecRegistry registry) { return new JacksonCodec<>(objectMapper, registry, type); } } 

编解码器本身:

 class JacksonCodec implements Codec { private final ObjectMapper objectMapper; private final Codec rawBsonDocumentCodec; private final Class type; public JacksonCodec(ObjectMapper objectMapper, CodecRegistry codecRegistry, Class type) { this.objectMapper = objectMapper; this.rawBsonDocumentCodec = codecRegistry.get(RawBsonDocument.class); this.type = type; } @Override public T decode(BsonReader reader, DecoderContext decoderContext) { try { RawBsonDocument document = rawBsonDocumentCodec.decode(reader, decoderContext); String json = document.toJson(); return objectMapper.readValue(json, type); } catch (IOException e) { throw new UncheckedIOException(e); } } @Override public void encode(BsonWriter writer, Object value, EncoderContext encoderContext) { try { String json = objectMapper.writeValueAsString(value); rawBsonDocumentCodec.encode(writer, RawBsonDocument.parse(json), encoderContext); } catch (IOException e) { throw new UncheckedIOException(e); } } @Override public Class getEncoderClass() { return this.type; } } 

当与Lombok和最新的Jackson注释结合使用时,它允许我们做这样的事情(几乎看起来不像Java代码,嗯?):

 @JsonIgnoreProperties(ignoreUnknown=true) @JsonDeserialize(builder = Account.AccountBuilder.class) @Builder(toBuilder=true) @Value public class Account { @JsonProperty private String _id; @JsonProperty private long _version; @JsonProperty private String organizationName; @JsonPOJOBuilder(withPrefix = "") public static final class AccountBuilder { } } 

然后:

 Account account = collection.find(eq("_id", id)).first(); System.out.println(account.getOrganizationName());