Автор оригинала: 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 .