使用 Java 驱动程序将带有 JsonNode 字段的 POJO 插入到 MongoDB 中

Inserting a POJO with a JsonNode field into MongoDB using Java driver

我正在使用 Mongo Java 驱动程序 3.7

这是我的 POJO(带有 getter 和 setter)-

public class Sample{
    public int field1;
    public JsonNode field2;
}

我正在使用以下代码将 Sample 对象插入 MongoDB。

MongoCollection<Sample> myCollection = database.getCollection("myCollection",Sample.class);
ObjectMapper mapper = new ObjectMapper();
    Sample obj = new Sample();
    obj.setField1(1);
    String sampleJSON = "{ \"key\": \"value\" }";
    obj.setField2(mapper.readTree(sample));

myCollection.insertOne(obj);

看到的输出:(JsonNode 字段为空

{
    "_id" : ObjectId("5afbff8a8f621e1e328a8c4e"),
    "field1" : 1
    "field2" : [
                 [ ]
               ],
}

注意: 在调试模式下,很明显 JsonNode 是用正确的数据创建的。但是 insert 行为不端。 我想我在这里遗漏了一些东西。任何潜在客户表示赞赏。

更新: 我尝试为 JsonNode class 编写自定义编解码器,但 mongo 从未使用过它。这是我的编解码器代码 -

@Slf4j
public class JsonNodeCodec implements CollectibleCodec<JsonNode> {
    @Inject
    private ObjectMapper objectMapper;

    @Override
    public JsonNode generateIdIfAbsentFromDocument(JsonNode jsonNode) {
        return null;
    }

    @Override
    public boolean documentHasId(JsonNode jsonNode) {
        return false;
    }

    @Override
    public BsonValue getDocumentId(JsonNode jsonNode) {
        return null;
    }

    @Override
    public JsonNode decode(BsonReader reader, DecoderContext decoderContext) {
        String task = reader.readString();
        JsonNode node = objectMapper.readTree(task);
        return node;
    }

    @Override
    public void encode(BsonWriter writer, JsonNode jsonNode, EncoderContext encoderContext) {
        writer.writeString(jsonNode.toString());
    }

    @Override
    public Class<JsonNode> getEncoderClass() {
        return JsonNode.class;
    }
}

我正在这样注册编解码器 -

Codec<JsonNode> jsonNodeCodec = new JsonNodeCodec();
CodecRegistry codecRegistry = CodecRegistries.fromRegistries(com.mongodb.MongoClient.getDefaultCodecRegistry(),
            CodecRegistries.fromCodecs(jsonNodeCodec),
            CodecRegistries.fromProviders(PojoCodecProvider.builder().automatic(true).build())
    );

PS:为自定义 POJO 注册的其他编解码器工作正常。但是此编解码器从未用于 encode/decode JSON 对象

我在这里遇到了同样的问题并使用 ObjectMapper 解决了。

使用如下:

ObjectMapper mapper =   new ObjectMapper();
Map inputMap        =   mapper.convertValue(jsonNode, Map.class);

只需添加自定义转换器即可将 JsonNode 对象转换为 org.bson.Document,反之亦然。保持你的 POJOs/Document 类 与 JsonNode 字段一样。如果使用 spring :

@Bean
public MongoCustomConversions mongoCustomConversions() {
    List<Converter<?, ?>> converters = new ArrayList<>();
    converters.add(JsonNodeToDocumentConverter.INSTANCE);
    converters.add(DocumentToJsonNodeConverter.INSTANCE);
    return new MongoCustomConversions(converters);
}

@WritingConverter
enum JsonNodeToDocumentConverter implements Converter<JsonNode, Document> {
    INSTANCE;

    public Document convert(JsonNode source) {
        if(source == null)
            return null;

        return Document.parse(source.toString());
    }
}

@ReadingConverter
enum DocumentToJsonNodeConverter implements Converter<Document, JsonNode> {
    INSTANCE;

    public JsonNode convert(Document source) {
        if(source == null)
            return null;

        ObjectMapper mapper = new ObjectMapper();
        try {
            return mapper.readTree(source.toJson());
        } catch (IOException e) {
            throw new RuntimeException("Unable to parse DbObject to JsonNode", e);
        }
    }
}