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 .