MongoDB
 sql >> Database >  >> NoSQL >> MongoDB

Conversione di documenti da BSON a JSON in Java

1. Panoramica

In questo articolo precedente, abbiamo visto come recuperare 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 una 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 esempio  entità 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 da BSON a JSON predefinita

Ora testiamo la conversione predefinita che è molto semplice:chiama semplicemente toJson metodo dal Documento BSON classe :

@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 expectedJson il valore è:

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

Sembra corrispondere a una mappatura JSON standard.

Tuttavia, possiamo vedere che la data è stata convertita per impostazione predefinita come oggetto con una $data campo in formato epoca. Vediamo ora come possiamo modificare questo formato di data.

4. Conversione rilassata della data da BSON a JSON

Ad esempio, se vogliamo una rappresentazione della data ISO più classica (come per un client JavaScript), possiamo passare il rilassato Modalità JSON su toJson metodo, utilizzando JsonWriterSettings.builder :

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

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

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

Questo formato sembra corretto, ma abbiamo ancora la $data campo:vediamo come sbarazzarcene utilizzando un convertitore personalizzato.

5. Conversione della data da BSON a JSON personalizzata

Innanzitutto, dobbiamo implementare il BSON Converter interfaccia per digitare Lungo , poiché i valori di data sono espressi in millisecondi dall'epoca dell'epoca. Stiamo utilizzando DateTimeFormatter.ISO_INSTANT per ottenere il formato di output previsto:

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

Quindi, possiamo passare un'istanza di questa classe come convertitore DateTime a JsonWriterSettings costruttore :

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

Infine, otteniamo un semplice formato di data ISO JSON :

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