Автор оригинала: Benjamin Caure.
1. Обзор
В этой предыдущей статье мы рассмотрели, как получить документы BSON в виде объектов Java из MongoDB.
Это очень распространенный способ разработки REST API, так как мы можем захотеть изменить эти объекты перед преобразованием их в JSON (например, с помощью Jackson).
Однако мы, возможно, не захотим ничего менять в наших документах. Чтобы избавить нас от необходимости кодировать подробное отображение объектов Java, мы можем использовать прямое преобразование документов BSON в JSON .
Давайте посмотрим, как MongoDB BSON API работает в этом случае использования.
2. Создание документа BSON в MongoDB с помощью морфия
Прежде всего, давайте настроим наши зависимости с помощью морфия, как описано в этой статье .
Вот наш пример сущность, которая включает в себя различные типы атрибутов:
@Entity("Books") public class Book { @Id private String isbn; @Embedded private Publisher publisher; @Property("price") private double cost; @Property private LocalDateTime publishDate; // Getters and setters ... }
Затем давайте создадим новую сущность BSON для нашего теста и сохраним ее в MongoDB:
public class BsonToJsonIntegrationTest { private static final String DB_NAME = "library"; private static Datastore datastore; @BeforeClass public static void setUp() { Morphia morphia = new Morphia(); morphia.mapPackage("com.baeldung.morphia"); datastore = morphia.createDatastore(new MongoClient(), DB_NAME); datastore.ensureIndexes(); datastore.save(new Book() .setIsbn("isbn") .setCost(3.95) .setPublisher(new Publisher(new ObjectId("fffffffffffffffffffffffa"),"publisher")) .setPublishDate(LocalDateTime.parse("2020-01-01T18:13:32Z", DateTimeFormatter.ISO_DATE_TIME))); } }
3. Преобразование документа BSON в JSON по умолчанию
Теперь давайте проверим преобразование по умолчанию, которое очень просто: просто вызовите метод | toJSON из класса BSON Document |:
@Test public void givenBsonDocument_whenUsingStandardJsonTransformation_thenJsonDateIsObjectEpochTime() { String json = null; try (MongoClient mongoClient = new MongoClient()) { MongoDatabase mongoDatabase = mongoClient.getDatabase(DB_NAME); Document bson = mongoDatabase.getCollection("Books").find().first(); assertEquals(expectedJson, bson.toJson()); } }
Ожидаемое значение Json равно:
{ "_id": "isbn", "className": "com.baeldung.morphia.domain.Book", "publisher": { "_id": { "$oid": "fffffffffffffffffffffffa" }, "name": "publisher" }, "price": 3.95, "publishDate": { "$date": 1577898812000 } }
Это, по-видимому, соответствует стандартному отображению JSON.
Однако мы видим, что дата была преобразована по умолчанию как объект с полем $date в формате epoch time . Давайте теперь посмотрим, как мы можем изменить этот формат даты.
4. Облегченное преобразование данных BSON в JSON
Например, если нам нужно более классическое представление данных ISO (например, для клиента JavaScript), мы можем передать режим relaxed JSON в метод toJSON , используя JsonWriterSettings.builder :
bson.toJson(JsonWriterSettings .builder() .outputMode(JsonMode.RELAXED) .build());
В результате мы можем увидеть “расслабленное” преобразование поля Дата публикации :
{ ... "publishDate": { "$date": "2020-01-01T17:13:32Z" } ... }
Этот формат кажется правильным, но у нас все еще есть поле $date — давайте посмотрим, как избавиться от него с помощью пользовательского конвертера.
5. Пользовательское преобразование данных BSON в JSON
Во-первых, мы должны реализовать BSON Конвертер интерфейс для типа Long , поскольку значения дат выражаются в миллисекундах с момента эпохи. Мы используем DateTimeFormatter.ISO_INSTANT для получения ожидаемого формата вывода:
public class JsonDateTimeConverter implements Converter{ private static final Logger LOGGER = LoggerFactory.getLogger(JsonDateTimeConverter.class); static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ISO_INSTANT .withZone(ZoneId.of("UTC")); @Override public void convert(Long value, StrictJsonWriter writer) { try { Instant instant = new Date(value).toInstant(); String s = DATE_TIME_FORMATTER.format(instant); writer.writeString(s); } catch (Exception e) { LOGGER.error(String.format("Fail to convert offset %d to JSON date", value), e); } } }
Затем мы можем передать экземпляр этого класса в качестве преобразователя даты и времени в JsonWriterSettings builder :
bson.toJson(JsonWriterSettings .builder() .dateTimeConverter(new JsonDateTimeConverter()) .build());
Наконец, мы получаем простой формат даты ISO JSON :
{ ... "publishDate": "2020-01-01T17:13:32Z" ... }
6. Заключение
В этой статье мы рассмотрели поведение преобразования документов BSON в JSON по умолчанию.
Мы выделили, как настроить формат даты, что является распространенной проблемой, с помощью BSON Converter .
Конечно, мы можем поступить таким же образом, чтобы преобразовать другие типы данных : число, логическое значение, нулевое значение или идентификатор объекта, например.
Как всегда, код можно найти на GitHub .