Convertendo JSON para CSV em Java
1. Introdução
Neste breve tutorial, veremos como usar Jackson para converter JSON em CSV e vice-versa.
Existem bibliotecas alternativas disponíveis, comoCDL class from org.json, mas vamos nos concentrar apenas na biblioteca Jackson aqui.
Depois de examinar nosso exemplo de estrutura de dados, usaremos uma combinação deObjectMapper e CSVMapper para converter entre JSON e CSV.
2. Dependências
Vamos adicionar a dependência do formatador de dados Jackson CSV:
com.fasterxml.jackson.dataformat
jackson-dataformat-csv
2.9.8
Sempre podemos encontrar a versão mais recente dessa dependência emMaven Central.
Também adicionaremos a dependência para o databind principal de Jackson:
com.fasterxml.jackson.core
jackson-databind
2.9.8
Novamente, podemos encontrar a versão mais recente dessa dependência emMaven Central.
3. Estrutura de dados
Antes de reformatar um documento JSON para CSV, precisamos considerar o quão bem nosso modelo de dados será mapeado entre os dois formatos.
Então, primeiro, vamos considerar quais dados os diferentes formatos suportam:
-
Usamos JSON para representar uma variedade de estruturas de objetos, incluindo aquelas que contêm matrizes e objetos aninhados
-
Usamos o CSV para representar dados de uma lista de objetos, com cada objeto da lista aparecendo em uma nova linha
Isso significa que, se nosso documento JSON tiver uma matriz de objetos, podemos reformatar cada objeto em uma nova linha do nosso arquivo CSV. Portanto, como exemplo, vamos usar um documento JSON contendo a seguinte lista de itens de um pedido:
[ {
"item" : "No. 9 Sprockets",
"quantity" : 12,
"unitPrice" : 1.23
}, {
"item" : "Widget (10mm)",
"quantity" : 4,
"unitPrice" : 3.45
} ]
Usaremos os nomes de campo do documento JSON como cabeçalhos de coluna e o reformataremos para o seguinte arquivo CSV:
item,quantity,unitPrice
"No. 9 Sprockets",12,1.23
"Widget (10mm)",4,3.45
4. Leia JSON e escreva CSV
Primeiro, usamosObjectMapper de Jackson para ler nosso documento JSON de exemplo em uma árvore de objetosJsonNode:
JsonNode jsonTree = new ObjectMapper().readTree(new File("src/main/resources/orderLines.json"));
A seguir, vamos criar umCsvSchema. Isso determina os cabeçalhos, os tipos e a sequência de colunas no arquivo CSV. Para fazer isso, criamos umCsvSchema Buildere definimos os cabeçalhos das colunas para corresponder aos nomes dos campos JSON:
Builder csvSchemaBuilder = CsvSchema.builder();
JsonNode firstObject = jsonTree.elements().next();
firstObject.fieldNames().forEachRemaining(fieldName -> {csvSchemaBuilder.addColumn(fieldName);} );
CsvSchema csvSchema = csvSchemaBuilder.build().withHeader();
Then, we create a CsvMapper with our CsvSchema, and finally, we write the jsonTree to our CSV file:
CsvMapper csvMapper = new CsvMapper();
csvMapper.writerFor(JsonNode.class)
.with(csvSchema)
.writeValue(new File("src/main/resources/orderLines.csv"), jsonTree);
Quando executamos esse código de amostra, nosso documento JSON de exemplo é convertido no arquivo CSV esperado.
5. Ler CSV e escrever JSON
Agora, vamos usarCsvMapper de Jackson para ler nosso arquivo CSV em umList de objetosOrderLine. Para fazer isso, primeiro criamos a classeOrderLine como um POJO simples:
public class OrderLine {
private String item;
private int quantity;
private BigDecimal unitPrice;
// Constructors, Getters, Setters and toString
}
Usaremos os cabeçalhos das colunas no arquivo CSV para definir nossoCsvSchema. Then,we use the CsvMapper to read the data from the CSV emMappingIterator de objetosOrderLine:
CsvSchema orderLineSchema = CsvSchema.emptySchema().withHeader();
CsvMapper csvMapper = new CsvMapper();
MappingIterator orderLines = csvMapper.readerFor(OrderLine.class)
.with(orderLineSchema)
.readValues(new File("src/main/resources/orderLines.csv"));
Em seguida, usaremosMappingIterator para obter umList de objetosOrderLine. Em seguida, usamosObjectMapper de Jackson para escrever a lista como um documento JSON:
new ObjectMapper()
.configure(SerializationFeature.INDENT_OUTPUT, true)
.writeValue(new File("src/main/resources/orderLinesFromCsv.json"), orderLines.readAll());
Quando executamos esse código de amostra, nosso arquivo CSV de exemplo é convertido no documento JSON esperado.
6. Configurando o formato de arquivo CSV
Vamos usar algumas das anotações de Jackson para ajustar o formato do arquivo CSV. Vamos mudar o título da coluna‘item' para‘name', o título da coluna‘quantity' para‘count', remover a coluna‘unitPrice' e fazer‘count' a primeira coluna.
Portanto, nosso arquivo CSV esperado se torna:
count,name
12,"No. 9 Sprockets"
4,"Widget (10mm)"
Criaremos uma nova classe abstrata para definir o formato necessário para o arquivo CSV:
@JsonPropertyOrder({
"count",
"name"
})
public abstract class OrderLineForCsv {
@JsonProperty("name")
private String item;
@JsonProperty("count")
private int quantity;
@JsonIgnore
private BigDecimal unitPrice;
}
Então, usamos nossa classeOrderLineForCsv para criar umCsvSchema:
CsvMapper csvMapper = new CsvMapper();
CsvSchema csvSchema = csvMapper
.schemaFor(OrderLineForCsv.class)
.withHeader();
Também usamosOrderLineForCsv como um Jackson Mixin. Isso diz a Jackson para usar as anotações que adicionamos à classeOrderLineForCsv quando ela processa um objetoOrderLine:
csvMapper.addMixIn(OrderLine.class, OrderLineForCsv.class);
Finalmente, usamos umObjectMapper para ler nosso documento JSON em uma matrizOrderLine, e usamos nossocsvMapper para escrever isso em um arquivo CSV:
OrderLine[] orderLines = new ObjectMapper()
.readValue(new File("src/main/resources/orderLines.json"), OrderLine[].class);
csvMapper.writerFor(OrderLine[].class)
.with(csvSchema)
.writeValue(new File("src/main/resources/orderLinesReformated.csv"), orderLines);
Quando executamos esse código de amostra, nosso documento JSON de exemplo é convertido no arquivo CSV esperado.
7. Conclusão
Neste tutorial rápido, aprendemos a ler e gravar arquivos CSV usando a biblioteca de formatos de dados Jackson. Também analisamos algumas opções de configuração que nos ajudam a obter nossos dados da maneira que queremos.
Como sempre, o código pode ser encontradoover on GitHub.