1. Overzicht
In dit vorige artikel hebben we gezien hoe u BSON-documenten kunt ophalen als Java-objecten van MongoDB.
Dit is een veelgebruikte manier om een REST API te ontwikkelen, omdat we deze objecten misschien willen wijzigen voordat ze naar JSON worden geconverteerd (bijvoorbeeld met Jackson).
Het kan echter zijn dat we niets willen veranderen aan onze documenten. Om ons de moeite te besparen om uitgebreide Java-objecten in kaart te brengen, kunnen we directe BSON naar JSON-documentconversie gebruiken .
Laten we eens kijken hoe MongoDB BSON API werkt voor deze use case.
2. BSON Documentcreatie in MongoDB met Morphia
Laten we allereerst onze afhankelijkheden instellen met Morphia zoals beschreven in dit artikel.
Hier is ons voorbeeld entiteit die verschillende attribuuttypes bevat:
@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 ...
}
Laten we dan een nieuwe BSON-entiteit maken voor onze test en deze opslaan 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. Standaard BSON naar JSON-documentconversie
Laten we nu de standaardconversie testen, die heel eenvoudig is:bel gewoon toJson methode uit het BSON Document klas :
@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());
}
}
De verwachteJson waarde is:
{
"_id": "isbn",
"className": "com.baeldung.morphia.domain.Book",
"publisher": {
"_id": {
"$oid": "fffffffffffffffffffffffa"
},
"name": "publisher"
},
"price": 3.95,
"publishDate": {
"$date": 1577898812000
}
}
Dit lijkt overeen te komen met een standaard JSON-mapping.
We kunnen echter zien dat de datum standaard is geconverteerd als een object met een $date veld in epoche-tijdformaat. Laten we nu kijken hoe we deze datumnotatie kunnen wijzigen.
4. Ontspannen BSON naar JSON-datumconversie
Als we bijvoorbeeld een meer klassieke ISO-datumweergave willen (zoals voor een JavaScript-client), kunnen we de relaxed doorgeven JSON-modus naar de toJson methode, met behulp van JsonWriterSettings.builder :
bson.toJson(JsonWriterSettings
.builder()
.outputMode(JsonMode.RELAXED)
.build());
Als resultaat kunnen we de publishDate . zien "ontspannen" conversie van het veld:
{
...
"publishDate": {
"$date": "2020-01-01T17:13:32Z"
}
...
}
Dit formaat lijkt correct, maar we hebben nog steeds de $date veld — laten we eens kijken hoe we er vanaf kunnen komen met een aangepaste converter.
5. Aangepaste BSON naar JSON-datumconversie
Eerst moeten we de BSON Converter . implementeren interface voor type Lang , aangezien datumwaarden worden uitgedrukt in milliseconden sinds tijdperk. We gebruiken DateTimeFormatter.ISO_INSTANT om het verwachte uitvoerformaat te krijgen:
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);
}
}
}
Vervolgens kunnen we een instantie van deze klasse als een DateTime-converter doorgeven aan de JsonWriterSettings bouwer :
bson.toJson(JsonWriterSettings
.builder()
.dateTimeConverter(new JsonDateTimeConverter())
.build());
Ten slotte krijgen we een eenvoudig JSON ISO-datumformaat :
{
...
"publishDate": "2020-01-01T17:13:32Z"
...
}