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

时间:2018-05-16 10:07:18

标签: json mongodb jackson mongo-java-driver

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

这是我的POJO(有吸气剂和制定者) -

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是使用适当的数据创建的。但是插入行为是行为不端的。 我想我在这里遗漏了一些东西。任何线索都赞赏。

更新 我尝试为JsonNode类编写自定义编解码器,但它永远不会被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注册的其他编解码器工作正常。但是这个编解码器永远不会用于编码/解码JSON对象

2 个答案:

答案 0 :(得分:2)

只需添加自定义转换器即可将JsonNode对象转换为org.bson.Document,反之亦然。保持POJO / 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);
        }
    }
}

答案 1 :(得分:1)

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

在下面使用:

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