MongoDB
 sql >> Base de Dados >  >> NoSQL >> MongoDB

Conversão de documentos BSON para JSON em Java

1. Visão geral


Neste artigo anterior, vimos como recuperar documentos BSON como objetos Java do MongoDB.

Essa é uma maneira muito comum de desenvolver uma API REST, pois podemos querer modificar esses objetos antes de convertê-los em JSON (usando Jackson, por exemplo).

No entanto, talvez não queiramos alterar nada em nossos documentos. Para evitar o problema de codificar o mapeamento detalhado de objetos Java, podemos usar a conversão direta de documentos BSON para JSON .

Vamos ver como a API MongoDB BSON funciona para este caso de uso.

2. Criação de documentos BSON no MongoDB com Morphia


Antes de tudo, vamos configurar nossas dependências usando o Morphia conforme descrito neste artigo.

Aqui está nosso exemplo  entidade que inclui vários tipos de atributos:
@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 ...
}

Então vamos criar uma nova entidade BSON para nosso teste e salvá-la no 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. Conversão de documento BSON para JSON padrão


Agora vamos testar a conversão padrão que é bem simples:basta chamar toJson método do 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());
     }
}

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

Isso parece corresponder a um mapeamento JSON padrão.

No entanto, podemos ver que a data foi convertida por padrão como um objeto com um $date campo no formato de tempo de época. Vamos ver agora como podemos mudar esse formato de data.

4. Conversão de data BSON para JSON relaxada


Por exemplo, se quisermos uma representação de data ISO mais clássica (como para um cliente JavaScript), podemos passar o método relaxado Modo JSON para o toJson método, usando JsonWriterSettings.builder :
bson.toJson(JsonWriterSettings
  .builder()
  .outputMode(JsonMode.RELAXED)
  .build());

Como resultado, podemos ver a publishDate conversão “relaxada” do campo:
{
    ...
    "publishDate": {
        "$date": "2020-01-01T17:13:32Z"
    }
    ...
}

Este formato parece correto, mas ainda temos o $date field — vamos ver como se livrar dele usando um conversor personalizado.

5. Conversão de data BSON para JSON personalizada


Primeiro, temos que implementar o BSON Converter interface para o tipo Longo , pois os valores de data são expressos em milissegundos desde a época. Estamos usando DateTimeFormatter.ISO_INSTANT para obter o formato de saída esperado:
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);
        }
    }
}

Então, podemos passar uma instância desta classe como um conversor DateTime para o JsonWriterSettings construtor :
bson.toJson(JsonWriterSettings
  .builder()
  .dateTimeConverter(new JsonDateTimeConverter())
  .build());

Por fim, obtemos um formato de data ISO JSON simples :
{
    ...
    "publishDate": "2020-01-01T17:13:32Z"
    ...
}