使用 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);
}
}
}
我正在使用 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);
}
}
}