1. Ikhtisar
Dalam artikel sebelumnya, kita telah melihat cara mengambil dokumen BSON sebagai objek Java dari MongoDB.
Ini adalah cara yang sangat umum untuk mengembangkan REST API, karena kita mungkin ingin memodifikasi objek ini sebelum mengonversinya ke JSON (menggunakan Jackson misalnya).
Namun, kami mungkin tidak ingin mengubah apa pun pada dokumen kami. Untuk menyelamatkan kita dari kesulitan mengkodekan pemetaan objek Java verbose, kita dapat menggunakan konversi dokumen BSON ke JSON langsung .
Mari kita lihat bagaimana MongoDB BSON API bekerja untuk kasus penggunaan ini.
2. Pembuatan Dokumen BSON di MongoDB dengan Morphia
Pertama-tama, mari kita siapkan dependensi kita menggunakan Morphia seperti yang dijelaskan dalam artikel ini.
Ini contoh kami entitas yang mencakup berbagai jenis atribut:
@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 ...
}
Lalu mari buat entitas BSON baru untuk pengujian kita dan simpan ke 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. Konversi Dokumen BSON ke JSON Default
Sekarang mari kita uji konversi default yang sangat sederhana:cukup panggil keJson metode dari Dokumen BSON kelas :
@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 yang diharapkan nilainya adalah:
{
"_id": "isbn",
"className": "com.baeldung.morphia.domain.Book",
"publisher": {
"_id": {
"$oid": "fffffffffffffffffffffffa"
},
"name": "publisher"
},
"price": 3.95,
"publishDate": {
"$date": 1577898812000
}
}
Ini tampaknya sesuai dengan pemetaan JSON standar.
Namun, kita dapat melihat bahwa tanggal telah dikonversi secara default sebagai objek dengan $date bidang dalam format waktu zaman. Mari kita lihat sekarang bagaimana kita dapat mengubah format tanggal ini.
4. Konversi Tanggal BSON ke JSON yang Santai
Misalnya, jika kita menginginkan representasi tanggal ISO yang lebih klasik (seperti untuk klien JavaScript), kita dapat meneruskan santai mode JSON ke keJson metode, menggunakan JsonWriterSettings.builder :
bson.toJson(JsonWriterSettings
.builder()
.outputMode(JsonMode.RELAXED)
.build());
Hasilnya, kita dapat melihat publishDate konversi "santai" bidang:
{
...
"publishDate": {
"$date": "2020-01-01T17:13:32Z"
}
...
}
Format ini tampaknya benar, tetapi kami masih memiliki $date bidang — mari kita lihat cara menghilangkannya menggunakan konverter khusus.
5. Konversi Tanggal BSON ke JSON Kustom
Pertama, kita harus mengimplementasikan BSON Konverter antarmuka untuk tipe Panjang , karena nilai tanggal dinyatakan dalam milidetik sejak waktu Epoch. Kami menggunakan DateTimeFormatter.ISO_INSTANT untuk mendapatkan format keluaran yang diharapkan:
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);
}
}
}
Kemudian, kita dapat meneruskan instance kelas ini sebagai konverter DateTime ke JsonWriterSettings pembangun :
bson.toJson(JsonWriterSettings
.builder()
.dateTimeConverter(new JsonDateTimeConverter())
.build());
Akhirnya, kami mendapatkan format tanggal ISO JSON biasa :
{
...
"publishDate": "2020-01-01T17:13:32Z"
...
}