Conversione di documenti da BSON a JSON in Java

Java Top

Ho appena annunciato il nuovo corso Learn Spring , incentrato sui fondamenti di Spring 5 e Spring Boot 2:

>> SCOPRI IL CORSO

1. Panoramica

In questo articolo precedente, abbiamo visto come recuperare i documenti BSON come oggetti Java da MongoDB.

Questo è un modo molto comune per sviluppare un'API REST, poiché potremmo voler modificare questi oggetti prima di convertirli in JSON (usando Jackson per esempio).

Tuttavia, potremmo non voler modificare nulla ai nostri documenti. Per risparmiarci la fatica di codificare la mappatura dettagliata di oggetti Java, possiamo utilizzare la conversione diretta di documenti da BSON a JSON .

Vediamo come funziona l'API BSON MongoDB per questo caso d'uso.

2. Creazione di documenti BSON in MongoDB con Morphia

Prima di tutto, impostiamo le nostre dipendenze usando Morphia come descritto in questo articolo.

Ecco il nostro esempioentità che include vari tipi di attributi:

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

Quindi creiamo una nuova entità BSON per il nostro test e salviamola 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. Conversione di documenti predefinita da BSON a JSON

Ora testiamo la conversione predefinita che è molto semplice: chiama semplicemente il metodo toJson dalla 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()); } }

Il valore Json atteso è:

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

Questo sembra corrispondere a una mappatura JSON standard.

Tuttavia, possiamo vedere che la data è stata convertita per impostazione predefinita come un oggetto con un campo $ date nel formato epoch time. Vediamo ora come possiamo cambiare questo formato di data.

4. Conversione della data da BSON a JSON rilassata

Ad esempio, se vogliamo una rappresentazione della data ISO più classica (come per un client JavaScript), possiamo passare la modalità JSON rilassata al metodo toJson , utilizzando JsonWriterSettings.builder :

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

Di conseguenza, possiamo vedere la conversione "rilassata" del campo publishDate :

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

Questo formato sembra corretto, ma abbiamo ancora il campo $ date : vediamo come eliminarlo utilizzando un convertitore personalizzato.

5. Conversione della data da BSON personalizzata a JSON

Innanzitutto, dobbiamo implementare l' interfaccia BSON Converter per il tipo Long , poiché i valori di data sono espressi in millisecondi dall'epoca. Stiamo usando DateTimeFormatter.ISO_INSTANT per ottenere il formato di output previsto:

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

Quindi, possiamo passare un'istanza di questa classe come convertitore DateTime al builder JsonWriterSettings :

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

Infine, otteniamo un semplice formato di data ISO JSON :

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

6. Conclusione

In questo articolo, abbiamo visto il comportamento predefinito della conversione di documenti da BSON a JSON.

Abbiamo evidenziato come personalizzare il formato della data, che è un problema comune, utilizzando BSON Converter .

Naturalmente, possiamo procedere allo stesso modo per convertire altri tipi di dati : numero, booleano, valore nullo o id oggetto, ad esempio.

Come sempre, il codice può essere trovato su GitHub.

Fondo Java

Ho appena annunciato il nuovo corso Learn Spring , incentrato sui fondamenti di Spring 5 e Spring Boot 2:

>> SCOPRI IL CORSO