Перейти к основному содержимому

Преобразование JSON в CSV в Java

· 4 мин. чтения

1. Введение

В этом кратком руководстве мы увидим, как использовать Jackson для преобразования JSON в CSV и наоборот.

Доступны альтернативные библиотеки, такие как класс CDL из org.json , но здесь мы сосредоточимся только на библиотеке Джексона.

После того, как мы рассмотрели наш пример структуры данных, мы будем использовать комбинацию ObjectMapper и CSVMapper для преобразования между JSON и CSV.

2. Зависимости

Давайте добавим зависимость для средства форматирования данных Jackson CSV:

<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-csv</artifactId>
<version>2.13.0</version>
</dependency>

Мы всегда можем найти самую последнюю версию этой зависимости на Maven Central .

Мы также добавим зависимость для основной привязки данных Jackson:

<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.13.0</version>
</dependency>

Опять же, самую последнюю версию этой зависимости мы можем найти на Maven Central .

3. Структура данных

Прежде чем мы переформатируем документ JSON в CSV, нам нужно подумать, насколько хорошо наша модель данных будет отображаться между двумя форматами.

Итак, сначала давайте рассмотрим, какие данные поддерживают разные форматы:

  • Мы используем JSON для представления различных структур объектов, в том числе содержащих массивы и вложенные объекты.
  • Мы используем CSV для представления данных из списка объектов, при этом каждый объект из списка появляется в новой строке.

Это означает, что если наш документ JSON имеет массив объектов, мы можем переформатировать каждый объект в новую строку нашего CSV-файла. Итак, в качестве примера возьмем документ JSON, содержащий следующий список товаров из заказа:

[ {
"item" : "No. 9 Sprockets",
"quantity" : 12,
"unitPrice" : 1.23
}, {
"item" : "Widget (10mm)",
"quantity" : 4,
"unitPrice" : 3.45
} ]

Мы будем использовать имена полей из документа JSON в качестве заголовков столбцов и переформатируем их в следующий файл CSV:

item,quantity,unitPrice
"No. 9 Sprockets",12,1.23
"Widget (10mm)",4,3.45

4. Чтение JSON и запись CSV

Во-первых, мы используем ObjectMapper Джексона для чтения нашего примера JSON-документа в дерево объектов JsonNode :

JsonNode jsonTree = new ObjectMapper().readTree(new File("src/main/resources/orderLines.json"));

Далее создадим CsvSchema . Это определяет заголовки столбцов, типы и последовательность столбцов в файле CSV. Для этого мы создаем CsvSchema Builder и устанавливаем заголовки столбцов в соответствии с именами полей JSON:

Builder csvSchemaBuilder = CsvSchema.builder();
JsonNode firstObject = jsonTree.elements().next();
firstObject.fieldNames().forEachRemaining(fieldName -> {csvSchemaBuilder.addColumn(fieldName);} );
CsvSchema csvSchema = csvSchemaBuilder.build().withHeader();

Затем мы создаем CsvMapper с нашей CsvSchema и, наконец, записываем jsonTree в наш CSV-файл :

CsvMapper csvMapper = new CsvMapper();
csvMapper.writerFor(JsonNode.class)
.with(csvSchema)
.writeValue(new File("src/main/resources/orderLines.csv"), jsonTree);

Когда мы запускаем этот пример кода, наш пример документа JSON преобразуется в ожидаемый файл CSV.

5. Чтение CSV и запись JSON

Теперь давайте воспользуемся CsvMapper Джексона, чтобы прочитать наш CSV-файл в список объектов OrderLine . Для этого мы сначала создадим класс OrderLine как простой POJO:

public class OrderLine {
private String item;
private int quantity;
private BigDecimal unitPrice;

// Constructors, Getters, Setters and toString
}

Мы будем использовать заголовки столбцов в CSV-файле для определения нашей CsvSchema . Затем мы используем CsvMapper для чтения данных из CSV в MappingIterator объектов OrderLine :

CsvSchema orderLineSchema = CsvSchema.emptySchema().withHeader();
CsvMapper csvMapper = new CsvMapper();
MappingIterator<OrderLine> orderLines = csvMapper.readerFor(OrderLine.class)
.with(orderLineSchema)
.readValues(new File("src/main/resources/orderLines.csv"));

Далее мы будем использовать MappingIterator для получения списка объектов OrderLine . Затем мы используем ObjectMapper Джексона, чтобы записать список в виде документа JSON:

new ObjectMapper()
.configure(SerializationFeature.INDENT_OUTPUT, true)
.writeValue(new File("src/main/resources/orderLinesFromCsv.json"), orderLines.readAll());

Когда мы запускаем этот пример кода, наш пример файла CSV преобразуется в ожидаемый документ JSON.

6. Настройка формата файла CSV

Давайте воспользуемся некоторыми аннотациями Джексона, чтобы настроить формат CSV-файла. Мы изменим заголовок столбца «элемент» на «имя» , заголовок столбца «количество» на «количество» , удалим столбец «единица измерения» и сделаем «количество» первым столбцом.

Итак, наш ожидаемый CSV-файл становится таким:

count,name
12,"No. 9 Sprockets"
4,"Widget (10mm)"

Мы создадим новый абстрактный класс для определения требуемого формата CSV-файла:

@JsonPropertyOrder({
"count",
"name"
})
public abstract class OrderLineForCsv {

@JsonProperty("name")
private String item;

@JsonProperty("count")
private int quantity;

@JsonIgnore
private BigDecimal unitPrice;

}

Затем мы используем наш класс OrderLineForCsv для создания CsvSchema :

CsvMapper csvMapper = new CsvMapper();
CsvSchema csvSchema = csvMapper
.schemaFor(OrderLineForCsv.class)
.withHeader();

Мы также используем OrderLineForCsv в качестве миксина Джексона. Это говорит Джексону использовать аннотации, которые мы добавили в класс OrderLineForCsv , когда он обрабатывает объект OrderLine :

csvMapper.addMixIn(OrderLine.class, OrderLineForCsv.class);

Наконец, мы используем ObjectMapper для чтения нашего документа JSON в массив OrderLine и используем наш csvMapper для записи этого в файл 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);

Когда мы запускаем этот пример кода, наш пример документа JSON преобразуется в ожидаемый файл CSV.

7. Заключение

В этом кратком руководстве мы узнали, как читать и записывать файлы CSV, используя библиотеку форматов данных Jackson. Мы также рассмотрели несколько параметров конфигурации, которые помогают нам придать нашим данным желаемый вид.

Как всегда, код можно найти на GitHub .