1. Въведение
В този кратък урок ще видим как да използваме Jackson за конвертиране на JSON в CSV и обратно.
Налични са алтернативни библиотеки, като клас CDL от org.json, но тук ще се съсредоточим само върху библиотеката на Джаксън.
След като разгледахме нашата примерна структура от данни, ще използваме комбинация от ObjectMapper и CSVMapper, за да конвертираме между JSON и CSV.
2. Зависимости
Нека добавим зависимостта за Jackson CSV форматиране на данни:
com.fasterxml.jackson.dataformat jackson-dataformat-csv 2.11.1
Винаги можем да намерим най-новата версия на тази зависимост на Maven Central.
Ще добавим и зависимостта за основната връзка на данни на Джаксън:
com.fasterxml.jackson.core jackson-databind 2.11.1
Отново можем да намерим най-новата версия на тази зависимост от 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 на Jackson, за да прочетем нашия примерен 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 orderLines = csvMapper.readerFor(OrderLine.class) .with(orderLineSchema) .readValues(new File("src/main/resources/orderLines.csv"));
След това ще използваме MappingIterator, за да получим Списък на обектите OrderLine . След това използваме ObjectMapper на Jackson, за да запишем списъка като JSON документ:
new ObjectMapper() .configure(SerializationFeature.INDENT_OUTPUT, true) .writeValue(new File("src/main/resources/orderLinesFromCsv.json"), orderLines.readAll());
Когато стартираме този примерен код, нашият примерен CSV файл се преобразува в очаквания JSON документ.
6. Конфигуриране на CSV файлов формат
Нека използваме някои от анотациите на Джаксън, за да коригираме формата на CSV файла. Ще променим заглавието на колоната „item“ на „name“ , заглавието на колоната „количество“ на „count“ , ще премахнем колоната „unitPrice“ и ще направим „count“ първата колона.
И така, нашият очакван 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 като Jackson Mixin. Това казва на Джаксън да използва поясненията, които добавихме към класа 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.