1. Übersicht
In diesem vorherigen Artikel haben wir gesehen, wie BSON-Dokumente als Java-Objekte aus MongoDB abgerufen werden.
Dies ist eine sehr gängige Methode zum Entwickeln einer REST-API, da wir diese Objekte möglicherweise ändern möchten, bevor wir sie in JSON konvertieren (z. B. mit Jackson).
Wir möchten jedoch möglicherweise nichts an unseren Dokumenten ändern. Um uns die Mühe zu ersparen, eine ausführliche Java-Objektzuordnung zu codieren, können wir direkte BSON-zu-JSON-Dokumentkonvertierung verwenden .
Mal sehen, wie die MongoDB BSON API für diesen Anwendungsfall funktioniert.
2. BSON-Dokumenterstellung in MongoDB mit Morphia
Lassen Sie uns zunächst unsere Abhängigkeiten mit Morphia einrichten, wie in diesem Artikel beschrieben.
Hier ist unser Beispiel Entität, die verschiedene Attributtypen enthält:
@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 ...
}
Dann erstellen wir eine neue BSON-Entität für unseren Test und speichern sie in 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. Standardkonvertierung von BSON-zu-JSON-Dokumenten
Lassen Sie uns nun die Standardkonvertierung testen, die sehr einfach ist:Rufen Sie einfach toJson auf -Methode aus dem BSON Dokument Klasse :
@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());
}
}
Der erwartete Json Wert ist:
{
"_id": "isbn",
"className": "com.baeldung.morphia.domain.Book",
"publisher": {
"_id": {
"$oid": "fffffffffffffffffffffffa"
},
"name": "publisher"
},
"price": 3.95,
"publishDate": {
"$date": 1577898812000
}
}
Dies scheint einer Standard-JSON-Zuordnung zu entsprechen.
Wir können jedoch sehen, dass das Datum standardmäßig als Objekt mit einem $date konvertiert wurde Feld im Epochenzeitformat. Sehen wir uns nun an, wie wir dieses Datumsformat ändern können.
4. Entspannte BSON-zu-JSON-Datumskonvertierung
Wenn wir beispielsweise eine klassischere ISO-Datumsdarstellung wünschen (z. B. für einen JavaScript-Client), können wir relaxed übergeben JSON-Modus zum toJson -Methode mithilfe von JsonWriterSettings.builder :
bson.toJson(JsonWriterSettings
.builder()
.outputMode(JsonMode.RELAXED)
.build());
Als Ergebnis können wir das publishDate sehen "entspannte" Konvertierung des Felds:
{
...
"publishDate": {
"$date": "2020-01-01T17:13:32Z"
}
...
}
Dieses Format scheint korrekt zu sein, aber wir haben immer noch das $date -Feld — mal sehen, wie man es mit einem benutzerdefinierten Konverter loswird.
5. Benutzerdefinierte BSON-zu-JSON-Datumskonvertierung
Zuerst müssen wir den BSON Converter implementieren Schnittstelle für geben Sie Long ein , da Datumswerte in Millisekunden seit Epochenzeit ausgedrückt werden. Wir verwenden DateTimeFormatter.ISO_INSTANT um das erwartete Ausgabeformat zu erhalten:
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);
}
}
}
Dann können wir eine Instanz dieser Klasse als DateTime-Konverter an JsonWriterSettings übergeben Baumeister :
bson.toJson(JsonWriterSettings
.builder()
.dateTimeConverter(new JsonDateTimeConverter())
.build());
Schließlich erhalten wir ein einfaches JSON-ISO-Datumsformat :
{
...
"publishDate": "2020-01-01T17:13:32Z"
...
}