1. Общ преглед
В тази предишна статия видяхме как да извличаме BSON документи като Java обекти от MongoDB.
Това е много често срещан начин за разработване на REST API, тъй като може да искаме да модифицираме тези обекти, преди да ги конвертираме в JSON (с помощта на Jackson например).
Въпреки това, може да не искаме да променяме нищо в нашите документи. За да ни спести проблемите с кодирането на подробно картографиране на Java обекти, можем да използваме директно преобразуване на BSON в JSON документ .
Нека видим как MongoDB BSON API работи за този случай на употреба.
2. Създаване на BSON документ в MongoDB с Morphia
Първо, нека настроим нашите зависимости с помощта на Morphia, както е описано в тази статия.
Ето нашия пример обект, който включва различни типове атрибути:
@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 класа :
@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 поле във формат за епоха. Нека видим сега как можем да променим този формат на датата.
4. Облекчено преобразуване на дата от BSON в JSON
Например, ако искаме по-класическо ISO представяне на датата (като за JavaScript клиент), можем да предадем спокойно JSON режим към toJson метод, използвайки JsonWriterSettings.builder :
bson.toJson(JsonWriterSettings
.builder()
.outputMode(JsonMode.RELAXED)
.build());
В резултат на това можем да видим Дата на публикуване „отпуснато“ преобразуване на полето:
{
...
"publishDate": {
"$date": "2020-01-01T17:13:32Z"
}
...
}
Този формат изглежда правилен, но все още имаме $date поле — нека видим как да се отървем от него с помощта на персонализиран конвертор.
5. Персонализирано преобразуване на дата от BSON в JSON
Първо, трябва да внедрим BSON конвертора интерфейса за тип Дълги , тъй като стойностите на датата се изразяват в милисекунди от времето на епохата. Използваме DateTimeFormatter.ISO_INSTANT за да получите очаквания изходен формат:
public class JsonDateTimeConverter implements Converter<Long> {
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);
}
}
}
След това можем да предадем екземпляр от този клас като преобразувател на DateTime към JsonWriterSettings строитела :
bson.toJson(JsonWriterSettings
.builder()
.dateTimeConverter(new JsonDateTimeConverter())
.build());
Накрая получаваме обикновен JSON ISO формат за дата :
{
...
"publishDate": "2020-01-01T17:13:32Z"
...
}