将MongoDB 3中的Document对象转换为POJOS

我将一个带有java.util.Date字段的对象保存到MongoDB 3.2实例中。

ObjectMapper mapper = new ObjectMapper(); String json = mapper.writeValueAsString(myObject); collection.insertOne(Document.parse(json)); 

字符串包含:

 "captured": 1454549266735 

然后我从MongoDB实例中读取它:

  final Document document = collection.find(eq("key", value)).first(); final String json = document.toJson(); ObjectMapper mapper = new ObjectMapper(); mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); xx = mapper.readValue(json, MyClass.class); 

反序列化失败:

java.lang.RuntimeException:com.fasterxml.jackson.databind.JsonMappingException:无法从START_OBJECT标记中反序列化java.util.Date的实例

我看到“document.toJson()”创建的json字符串包含:

 "captured": { "$numberLong": "1454550216318" } 

而不是最初的(“捕获”:1454549266735)MongoDB文档说他们开始使用“MongoDB Extended Json”。 我试过jackson1和2解析它 – 没有运气。

将MongoDB 3提供的Document对象转换为Java POJO的最简单方法是什么? 也许我可以完全跳过Json()步骤?

我试过mongojack – 那个不支持MongoDB3。

看看MongoDB文档页面上列出的其他几个POJO映射器 – 它们都需要将自定义注释放到Java类中。

您应该定义并使用自定义JsonWriterSettings来微调JSON生成:

  JsonWriterSettings settings = JsonWriterSettings.builder() .int64Converter((value, writer) -> writer.writeNumber(value.toString())) .build(); String json = new Document("a", 12).append("b", 14L).toJson(settings); 

会产生:

  { "a" : 12, "b" : 14 } 

如果您不使用自定义设置,那么文档将生成扩展的json:

  { "a" : 12, "b" : { "$numberLong" : "14" } } 

这看起来像Mongo Java驱动程序错误,即使使用JsonMode.STRICT,Document.toJson也会使用非标准JSON。 以下错误https://jira.mongodb.org/browse/JAVA-2173中描述了此问题,我建议您投票。

解决方法是使用com.mongodb.util.JSON.serialize(document)。

看起来你在“myObject”中使用了Date对象。 在这种情况下,您应该使用实现JsonSerializer, JsonDeserializerDateSerializer ,然后将其注册到GsonBuilder 。 示例代码如下:

 public class My_DateSerializer implements JsonSerializer, JsonDeserializer { @Override public LocalDate deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { final String dateAsString = json.getAsString(); final DateTimeFormatter dtf = DateTimeFormat.forPattern(DATE_FORMAT); if (dateAsString.length() == 0) { return null; } else { return dtf.parseLocalDate(dateAsString); } } @Override public JsonElement serialize(LocalDate src, Type typeOfSrc, JsonSerializationContext context) { String retVal; final DateTimeFormatter dtf = DateTimeFormat.forPattern(DATE_FORMAT); if (src == null) { retVal = ""; } else { retVal = dtf.print(src); } return new JsonPrimitive(retVal); } } 

现在用GsonBuilder注册它:

 final GsonBuilder builder = new GsonBuilder() .registerTypeAdapter(LocalDate.class, new My_DateSerializer()); final Gson gson = builder.create(); 

我用我的mongo文档保存一个标签,该文件指定了存储的对象的原始类型。 然后我使用Gson用该类型的名称解析它。 首先,创建存储的Document

 private static Gson gson = new Gson(); public static Document ConvertToDocument(Object rd) { if (rd instanceof Document) return (Document)rd; String json = gson.toJson(rd); Document doc = Document.parse(json); doc.append(TYPE_FIELD, rd.getClass().getName()); return doc; } 

然后将文档读回Java中,

 public static Object ConvertFromDocument(Document doc) throws CAAException { String clazzName = doc.getString(TYPE_FIELD); if (clazzName == null) throw new RuntimeException("Document was not stored in the DB or got stored without becing created by itemToStoredDocument()"); Class clazz; try { clazz = (Class) Class.forName(clazzName); } catch (ClassNotFoundException e) { throw new CAAException("Could not load class " + clazzName, e); } json = com.mongodb.util.JSON.serialize(doc); return gson.fromJson(json, clazz); } 

感谢Aleksey指出JSON.serialize()。