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

时间:2016-02-04 19:26:39

标签: java json mongodb mongodb-java

我将一个带有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”。我试过杰克逊1和2解析它 - 没有运气。

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

我尝试了mongojack - 那个不支持MongoDB3。

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

4 个答案:

答案 0 :(得分:11)

您应该定义并使用自定义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" } }

答案 1 :(得分:5)

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

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

答案 2 :(得分:0)

看起来你在“myObject”中使用了Date对象。在这种情况下,您应该使用实现DateSerializer的{​​{1}},然后将其注册到JsonSerializer<LocalDate>, JsonDeserializer<LocalDate>。示例代码如下:

GsonBuilder

现在用GsonBuilder注册:

public class My_DateSerializer implements JsonSerializer<LocalDate>,
                                                          JsonDeserializer<LocalDate> {

@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);
}
}

答案 3 :(得分:0)

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

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()。