2016-02-04 8 views
7

Sto salvando un oggetto con un campo java.util.Date in un'istanza di MongoDB 3.2.conversione di oggetti documento in MongoDB 3 in POJOS

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

la stringa contiene:

"captured": 1454549266735 

poi ho letto che dall'istanza 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); 

la deserializzazione fallisce:

java.lang.RuntimeException: com.fasterxml.jackson.databind.JsonMappingException : Impossibile deserializzare istanza di java.util.Date fuori START_OBJECT gettone

vedo che la stringa JSON creato da "document.toJson()" contiene:

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

al posto di quello che era originariamente ("catturato": 1454549266735) I documenti MongoDB dicono che hanno iniziato a usare "MongoDB Extended Json". Ho provato sia Jackson 1 che 2 per analizzarlo - senza fortuna.

qual è il modo più semplice per convertire gli oggetti Documento forniti da MongoDB 3 in POJO Java? forse posso saltare completamente a JSON()?

Ho provato il mongojack, che non supporta MongoDB3.

Guardato un paio di altri mappatori POJO elencati nella pagina dei documenti MongoDB - tutti richiedono di inserire le loro annotazioni personalizzate in classi Java.

risposta

4

Questo sembra un bug del driver Mongo Java, dove Document.toJson offre JSON non standard anche se si utilizza JsonMode.STRICT. Questo problema è descritto nel seguente bug https://jira.mongodb.org/browse/JAVA-2173 per il quale ti incoraggio a votare.

Una soluzione alternativa è utilizzare com.mongodb.util.JSON.serialize (documento).

+0

com.mongodb.util.JSON.serialize (documento) è stato ritirato nelle nuove versioni – Gilian

0

Sembra che si stia utilizzando l'oggetto Date all'interno di "myObject". In tal caso, è necessario utilizzare uno DateSerializer che implementa JsonSerializer<LocalDate>, JsonDeserializer<LocalDate> e quindi registrarlo con GsonBuilder. Codice di esempio segue:

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

Ora registrarlo con GsonBuilder:

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

Si dovrebbe definire e utilizzare JsonWriterSettings personalizzati per ottimizzare la generazione JSON:

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

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

produrrà:

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

Se non utilizzerà le impostazioni personalizzate allora documento produrrà JSON estesa:

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

Modifica: solo un semplice e semplice Grazie. –

+0

Risposta perfetta! Grazie! – ADJ

0

risparmio un tag con il mio documento Mongo che specifica il tipo originale dell'oggetto memorizzato.Quindi uso Gson per analizzarlo con il nome di quel tipo. In primo luogo, per creare il documento memorizzato

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

quindi di leggere il documento di nuovo nel 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); 
} 

Grazie a Aleksey per aver ricordato JSON.serialize().

Problemi correlati