Подтвердить что ты не робот

Преобразование объектов Document в MongoDB 3 в 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: Невозможно десериализовать экземпляр java.util.Date из токена START_OBJECT

Я вижу, что строка json, созданная с помощью document.toJson(), содержит:

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

вместо того, что было первоначально ( "захвачено": 1454549266735) MongoDB сообщает, что они начали использовать "MongoDB Extended Json". Я попробовал оба Джексона 1 и 2 разобрать его - не повезло.

Каков самый простой способ конвертировать те объекты Document, предоставленные MongoDB 3, в Java POJO? возможно, я могу вообще пропустить шаг toJson()?

Я попробовал mongojack - тот не поддерживает MongoDB3.

Посмотрел на пару других маркеров POJO, перечисленных на странице документов MongoDB - все они требуют размещения своих пользовательских аннотаций для классов Java.

4b9b3361

Ответ 1

Вы должны определить и использовать пользовательские 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" } }

Ответ 2

Это выглядит как ошибка драйвера Mongo Java, где Document.toJson использует нестандартный JSON, даже если используется JsonMode.STRICT. Эта проблема описана в следующей ошибке https://jira.mongodb.org/browse/JAVA-2173, за которую я призываю вас голосовать.

Обходной путь заключается в использовании com.mongod.util.JSON.serialize(document).

Ответ 3

Похоже, вы используете объект Date внутри "myObject". В этом случае вы должны использовать 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();

Ответ 4

Я сохраняю тег с моим документом 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);
}

Спасибо Алексею за указание JSON.serialize().