2016-02-04 4 views
7

Ich speichere ein Objekt mit einem java.util.Date-Feld in eine MongoDB 3.2-Instanz.Konvertieren von Dokumentobjekten in MongoDB 3 in POJOS

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

der String enthält:

"captured": 1454549266735 

dann habe ich es aus dem MongoDB Beispiel lesen:

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

die Deserialisierung fehlschlägt:

java.lang.RuntimeException: com.fasterxml.jackson.databind.JsonMappingException : Kann nicht Instanz java.util.Date aus START_OBJECT Token deserialisieren

Ich sehe, dass die JSON-String von "document.toJson()" erstellt wurde, enthält:

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

statt dessen, was war Dort ursprünglich ("captured": 1454549266735) MongoDB-Dokumente sagen, dass sie "MongoDB Extended Json" zu verwenden begannen. Ich habe Jackson 1 und 2 ausprobiert, um es zu analysieren - kein Glück.

Was ist der einfachste Weg, um die von MongoDB 3 zur Verfügung gestellten Dokumentobjekte in Java POJOs umzuwandeln? vielleicht kann ich zu json() schritt ganz überspringen?

Ich versuchte Mongojack - das MongoDB3 nicht unterstützt.

Betrachtet mehrere andere POJO-Mapper, die auf der MongoDB-Dokumentseite aufgelistet sind - sie alle müssen ihre benutzerdefinierten Anmerkungen in Java-Klassen einfügen.

Antwort

4

Dies sieht aus wie Mongo Java-Treiber-Bug, wo Document.toJson Nicht-Standard-JSON profund, auch wenn JsonMode.STRICT verwendet wird. Dieses Problem wird im folgenden Fehler https://jira.mongodb.org/browse/JAVA-2173 beschrieben, für den ich Sie ermutigen, zu wählen.

Eine Problemumgehung ist die Verwendung von com.mongodb.util.JSON.serialize (Dokument).

+0

com.mongodb.util.JSON.serialize (Dokument) wurde in neuen Versionen veraltet – Gilian

0

Es scheint, als ob Sie Date-Objekt in "myObject" verwenden. In diesem Fall sollten Sie eine DateSerializer verwenden, die JsonSerializer<LocalDate>, JsonDeserializer<LocalDate> implementiert und dann mit GsonBuilder registrieren. Beispielcode folgt:

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

Jetzt registrieren es mit GsonBuilder:

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

sollten Sie definieren und benutzerdefinierte JsonWriterSettings verwenden, um JSON Generation Feinabstimmung:

JsonWriterSettings settings = JsonWriterSettings.builder() 
     .int64Converter((value, writer) -> writer.writeNumber(value.toString())) 
     .build(); 

String json = new Document("a", 12).append("b", 14L).toJson(settings); 

produzieren:

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

Wenn Sie benutzerdefinierte Einstellungen nicht dann verwenden Dokument erweitern json produzieren:

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

Edit: nur ein einfaches und ein einfaches Danke. –

+0

Perfekte Antwort! Vielen Dank! – ADJ

0

ich einen Tag mit meinem Mongo Dokument speichern, das die ursprüngliche Art des Objekts gespeichert angibt.Ich benutze dann Gson, um es mit dem Namen dieses Typs zu analysieren. Zuerst erstellen die gespeicherte Dokument

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

dann das Dokument zurück in die Java zu lesen,

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

Dank Aleksey für JSON.serialize Hinweis auf().

Verwandte Themen