Conversion de documents BSON vers JSON en Java

Haut Java

Je viens d'annoncer le nouveau cours Learn Spring , axé sur les principes de base de Spring 5 et Spring Boot 2:

>> VOIR LE COURS

1. Vue d'ensemble

Dans cet article précédent, nous avons vu comment récupérer des documents BSON en tant qu'objets Java à partir de MongoDB.

C'est une manière très courante de développer une API REST, car nous souhaitons peut-être modifier ces objets avant de les convertir en JSON (en utilisant Jackson par exemple).

Cependant, nous pourrions ne pas vouloir changer quoi que ce soit à nos documents. Pour nous éviter d'avoir à coder le mappage détaillé des objets Java, nous pouvons utiliser la conversion directe de documents BSON vers JSON .

Voyons comment l'API MongoDB BSON fonctionne pour ce cas d'utilisation.

2. Création de documents BSON dans MongoDB avec Morphia

Tout d'abord, configurons nos dépendances en utilisant Morphia comme décrit dans cet article.

Voici notre exempleentité qui comprend divers types d'attributs:

@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 ... }

Ensuite, créons une nouvelle entité BSON pour notre test et sauvegardons-la dans 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. Conversion de document BSON vers JSON par défaut

Maintenant, testons la conversion par défaut qui est très simple: appelez simplement la méthode toJson depuis la classe 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()); } }

La valeur expectJson est:

{ "_id": "isbn", "className": "com.baeldung.morphia.domain.Book", "publisher": { "_id": { "$oid": "fffffffffffffffffffffffa" }, "name": "publisher" }, "price": 3.95, "publishDate": { "$date": 1577898812000 } }

Cela semble correspondre à un mappage JSON standard.

Cependant, nous pouvons voir que la date a été convertie par défaut en tant qu'objet avec un champ $ date au format d'heure d'époque. Voyons maintenant comment nous pouvons changer ce format de date.

4. Conversion de date BSON en JSON assouplie

Par exemple, si nous voulons une représentation de date ISO plus classique (comme pour un client JavaScript), nous pouvons passer le mode JSON détendu à la méthode toJson , en utilisant JsonWriterSettings.builder :

bson.toJson(JsonWriterSettings .builder() .outputMode(JsonMode.RELAXED) .build());

En conséquence, nous pouvons voir la conversion "détendue" du champ publishDate :

{ ... "publishDate": { "$date": "2020-01-01T17:13:32Z" } ... }

Ce format semble correct, mais nous avons toujours le champ $ date - voyons comment s'en débarrasser à l'aide d'un convertisseur personnalisé.

5. Conversion de date BSON en JSON personnalisée

Tout d'abord, nous devons implémenter l' interface BSON Converter pour le type Long , car les valeurs de date sont exprimées en millisecondes depuis l'époque. Nous utilisons DateTimeFormatter.ISO_INSTANT pour obtenir le format de sortie attendu:

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); } } }

Ensuite, nous pouvons transmettre une instance de cette classe en tant que convertisseur DateTime au générateur JsonWriterSettings :

bson.toJson(JsonWriterSettings .builder() .dateTimeConverter(new JsonDateTimeConverter()) .build());

Enfin, nous obtenons un format de date ISO JSON simple :

{ ... "publishDate": "2020-01-01T17:13:32Z" ... }

6. Conclusion

Dans cet article, nous avons vu le comportement par défaut de la conversion de documents BSON en JSON.

Nous avons mis en évidence comment personnaliser le format de date, qui est un problème courant, à l'aide de BSON Converter .

Bien entendu, nous pouvons procéder de la même manière pour convertir d'autres types de données : nombre, booléen, valeur nulle ou id d'objet, par exemple.

Comme toujours, le code peut être trouvé sur GitHub.

Fond Java

Je viens d'annoncer le nouveau cours Learn Spring , axé sur les principes de base de Spring 5 et Spring Boot 2:

>> VOIR LE COURS