2016-02-04 26 views
7

我將具有java.util.Date字段的對象保存到MongoDB 3.2實例中。將MongoDB 3中的文檔對象轉換爲POJOS

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

字符串包含:

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

"captured": 1454549266735 

然後我從MongoDB實例閱讀: com.fasterxml.jackson.databind.JsonMappingException : 無法反序列化java.util.Date的實例進行START_OBJECT令牌

我看到,創建的JSON字符串 「document.toJson()」 中載:

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

,而不是什麼最初(「捕獲」:1454549266735) MongoDB文檔說他們開始使用「MongoDB擴展Json」。我試了傑克遜1和2來解析它 - 沒有運氣。

將MongoDB 3提供的Document對象轉換爲Java POJO最簡單的方法是什麼?也許我可以跳到JSON()一步?

我試過mongojack - 那個不支持MongoDB3。

看着MongoDB文檔頁面上列出的其他POJO映射器 - 它們都需要將自定義註釋放到Java類中。

回答

4

這看起來像Mongo Java驅動程序錯誤,即使使用JsonMode.STRICT,Document.toJson也會導出非標準JSON。下面的bug https://jira.mongodb.org/browse/JAVA-2173中對此進行了描述,我鼓勵您參與投票。

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

+0

com.mongodb.util.JSON.serialize(文檔)在新版本中被棄用 – Gilian

0

它看起來像你在「myObject」中使用Date對象。在這種情況下,您應該使用DateSerializer實施JsonSerializer<LocalDate>, JsonDeserializer<LocalDate>,然後使用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); 
} 
} 

現在有了GsonBuilder註冊它:

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

您應該定義和使用自定義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" } } 
+0

編輯:只是一個簡單而純粹的謝謝。 –

+0

完美答案!謝謝! – ADJ

0

我節省了標籤與我蒙戈文檔指定原始類型存儲的對象。然後我用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); 
} 

感謝阿列克謝您指出JSON.serialize()。