ããã¯ããªã«ãããããŠæžãããã®ïŒ
ãããŸã§CSVãèªã¿æžãããã®ã«ãOpenCSVãSuper CSVãªã©ã䜿ã£ãŠããã®ã§ãããJacksonã§ãCSVãã¡ã€ã«ã®èªã¿æžãã
ã§ããããšã¯ãªããšãªãç¥ã£ãŠãããã®ã®äœ¿ã£ãããšããããŸããã§ããã
ã¡ãã£ãšè©ŠããŠã¿ããããªããšæããŸãã
ã©ãããéãã¿ããã§ããã
GitHub - uniVocity/csv-parsers-comparison: Comparisons among all Java-based CSV parsers in existence
Jackson Data Format Module
Jacksonã§CSVãã¡ã€ã«ãèªã¿æžãããã¢ãžã¥ãŒã«ã¯ãJackson Data Format Moduleã®ã²ãšã€ã«ãªã£ãŠããŸããGitHubãªããžããªã¯ã
ãã¡ãã«ãªããŸãã
ãã®ãªããžããªã«å«ãŸããŠããã¢ãžã¥ãŒã«ã§ã¯ãCSVãpropertiesãtomlïŒ2.12.3ããïŒãyamlã«å¯Ÿå¿ããŠããŸãã
ããã¥ã¡ã³ãã¯ãWikiãCSVã¢ãžã¥ãŒã«å
ã®README.md
ãèŠãããšã«ãªããŸãã
Home · FasterXML/jackson-dataformats-text Wiki · GitHub
CsvSchema · FasterXML/jackson-dataformats-text Wiki · GitHub
ããšã¯ãJavadocã§ããã
Jackson-dataformat-CSV 2.12.3 API
DatabindãšCoreã«ãäŸåããŠããã®ã§ããã¡ããèŠããšããã§ãããã
Jacksonã§CSVãèªã¿æžããã
Jacksonã䜿ã£ãŠCSVãã¡ã€ã«ãèªã¿æžããããšãã£ãŠããåºæ¬ãšæãã®ã¯JSONãæ±ãæã«äœ¿ã£ãŠããJacksonã§ãã
CsvMapper
ãšããã¯ã©ã¹ããŸãã¯äœ¿ãããšã«ãªãã§ããããã¡ãã¯ObjectMapper
ã®ãµãã¯ã©ã¹ã ã£ããããŸãã
CsvMapper (Jackson-dataformat-CSV 2.12.3 API)
å®éã®ããŒã¿ã®èªã¿æžãã«äœ¿ãã®ããJackson Databindã®ã¯ã©ã¹ã ã£ããããŸãã
ãªããžã§ã¯ãïŒPOJOïŒã®ããããã£ã®èšå®ã«ã@JsonFormat
ãªã©ã®ã¢ãããŒã·ã§ã³ã䜿ã£ããããã®ãåãã§ãã
JSONã§ã¯ãªãã®ã§ããã
ãã®ãããå¿ ç¶çã«ãã®ãããã®æ å ±ãèŠãŠããããšã«ãªãã§ãããã
Home · FasterXML/jackson-databind Wiki · GitHub
Home · FasterXML/jackson-core Wiki · GitHub
ããšã¯ãç¹åŸŽçãªã®ãCsvSchema
ã§ããã
CsvSchema (Jackson-dataformat-CSV 2.12.3 API)
ãã¡ãã䜿ã£ãŠãCSVã®ã¹ããŒãå®çŸ©ãè¡ããŸããã¹ããŒãå®çŸ©ãšã¯ãCSVã®èªã¿æžãæã®èšå®ã«é¢ãã以äžã®ãããªé
ç®ã
æããŠããŸãã
- ã«ã©ã å®çŸ©ïŒããã©ã«ãã¯ç©ºïŒ
- ããããŒã®æç¡ïŒããã©ã«ãã¯ããããŒãªãïŒ
- å²ã¿æåã®å®çŸ©ïŒããã©ã«ãã¯
"
ïŒ - ã«ã©ã ã®åºåãæåïŒããã©ã«ãã¯`,'ïŒ
- é
åèŠçŽ ãåºåãããã®æåïŒããã©ã«ãã¯
:
ïŒ - æ¹è¡æåïŒããã©ã«ãã¯
\n
ïŒ - ãšã¹ã±ãŒãæåïŒããã©ã«ããªãïŒ
- æåã®ã¬ã³ãŒããç¡èŠãããã©ããïŒããã©ã«ãã¯ç¡èŠããªãïŒ
null
ãè¡šãæååïŒããã©ã«ãã¯ç©ºæåïŒ- ããããŒã¬ã³ãŒããååšããå Žåãã¹ããŒãå®çŸ©ã®ã«ã©ã åãããããŒåãšäžèŽããå¿ èŠããããïŒããã©ã«ãã¯äžèŽããªããŠããïŒ
å人çã«ã¯ããšã¹ã±ãŒãæåãèªã¿èŸŒã¿æã«ããå¹ããªãããšã«æ°ã¥ããªããŠããã£ããããããŸããâŠã
説æã¯ããã®ãããã«ããŠããã€ããã¿ãŒã³ãè©ŠããŠãã£ãŠã¿ãŸãããã
ãé¡
ãããªæãã§ãã£ãŠã¿ãŸãã
- CSVãã¡ã€ã«ã®èªã¿èŸŒã¿
- CSVãã¡ã€ã«ã®æžã蟌ã¿
- åºåãæå
,
ãå²ã¿æå"
ã®CSVãåºåãã- ããããŒæãç¡ãã®2ã€ã®ãã¿ãŒã³ã§åºåãã
- æžã蟌ã¿ã«äœ¿çšãããªããžã§ã¯ãã¯ã
String
ã®é åãèªåã§å®çŸ©ããã¯ã©ã¹ãã®2ã€ã§æ±ã
- åºåãæå
èªã¿èŸŒã¿æã¯Map
ãå
¥ããŠãæ±ããããã£ãã®ã§å
¥ããŸããããæžã蟌ã¿æã¯ãã©ããªãã®ã§ãããŸããâŠã
ç°å¢
ä»åã®ç°å¢ã¯ããã¡ãã§ãã
$ java --version openjdk 11.0.11 2021-04-20 OpenJDK Runtime Environment (build 11.0.11+9-Ubuntu-0ubuntu2.20.04) OpenJDK 64-Bit Server VM (build 11.0.11+9-Ubuntu-0ubuntu2.20.04, mixed mode, sharing) $ mvn --version Apache Maven 3.8.1 (05c21c65bdfed0f71a2f2ada8b84da59348c4c5d) Maven home: $HOME/.sdkman/candidates/maven/current Java version: 11.0.11, vendor: Ubuntu, runtime: /usr/lib/jvm/java-11-openjdk-amd64 Default locale: ja_JP, platform encoding: UTF-8 OS name: "linux", version: "5.4.0-72-generic", arch: "amd64", family: "unix"
MavenäŸåé¢ä¿ã¯ããã¡ãã
<dependencies> <dependency> <groupId>com.fasterxml.jackson.dataformat</groupId> <artifactId>jackson-dataformat-csv</artifactId> <version>2.12.3</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.datatype</groupId> <artifactId>jackson-datatype-jsr310</artifactId> <version>2.12.3</version> </dependency> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-api</artifactId> <version>5.7.1</version> <scope>test</scope> </dependency> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-engine</artifactId> <version>5.7.1</version> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <artifactId>maven-surefire-plugin</artifactId> <version>2.22.2</version> </plugin> </plugins> </build>
ãŸãã¯jackson-dataformat-csv
ãå¿
èŠã§ãããã¡ãã§ãjackson-databind
ããã³jackson-core
ãjackson-annotations
ã
æšç§»çã«åŒã蟌ãŸããŸãã
ãŸãããªããžã§ã¯ãã«ãããã³ã°ããéã«ã¯LocalDate
ã䜿ãããšã«ããã®ã§ãjackson-datatype-jsr310
ãå«ããŸããã
åäœç¢ºèªã¯ããã¹ãã³ãŒããåãããŠè¡ãããšã«ããŸãããâŠã¢ãµãŒã·ã§ã³ã¯ããŸããã§ãããã©ã
èªã¿èŸŒã¿å¯Ÿè±¡ã®CSVãã¡ã€ã«
èªã¿èŸŒã¿å¯Ÿè±¡ã®CSVãã¡ã€ã«ã¯ããããªæãã§çšæããŸããããé¡ã¯æžç±ã§ãã
ããããŒããã
src/test/resources/books.csv
isbn,title,price,publishDate 978-4621303252,Effective Java 第3ç,"4400","2018-10-30" 978-4798151120,ç¬ç¿Java,3278,2019-05-15 978-4295008477,"æ°äžä»£Javaããã°ã©ãã³ã°ã¬ã€ã[Java SE 10/11/12/13ãšèšèªæ¡åŒµãããžã§ã¯ã]",2860,2020-03-13 "978-4774189093","Javaæ¬æ Œå ¥é \"ã¢ãã³ã¹ã¿ã€ã«ã«ããåºç€ãããªããžã§ã¯ãæåã»å®çšã©ã€ãã©ãªãŸã§\"",3278,2017-04-18 978-4774166858,æ¹èš2ç ããŒãã§ã¯ãJava,3520,2014-11-01
ããããŒãªãã
src/test/resources/books_headerless.csv
978-4621303252,Effective Java 第3ç,"4400","2018-10-30" 978-4798151120,ç¬ç¿Java,3278,2019-05-15 978-4295008477,"æ°äžä»£Javaããã°ã©ãã³ã°ã¬ã€ã[Java SE 10/11/12/13ãšèšèªæ¡åŒµãããžã§ã¯ã]",2860,2020-03-13 "978-4774189093","Javaæ¬æ Œå ¥é \"ã¢ãã³ã¹ã¿ã€ã«ã«ããåºç€ãããªããžã§ã¯ãæåã»å®çšã©ã€ãã©ãªãŸã§\"",3278,2017-04-18 978-4774166858,æ¹èš2ç ããŒãã§ã¯ãJava,3520,2014-11-01
å²ã¿æåã®æç¡ã¯ãé©åœã«ä»èŸŒãã§ããŸãã
ãããã³ã°å ã®ã¯ã©ã¹
CSVãã¡ã€ã«ãèªã¿èŸŒãã å 容ããèªåã§äœã£ããªããžã§ã¯ãã«ãããã³ã°ããå Žåã®ã¯ã©ã¹ã
src/test/java/org/littlewings/jackson/csv/Book.java
package org.littlewings.jackson.csv; import java.time.LocalDate; import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonPropertyOrder; @JsonPropertyOrder({"isbn", "title", "price", "publishDate"}) // for CsvMapper#schemaFor public class Book { String isbn; String title; int price; @JsonFormat(pattern = "yyyy-MM-dd") LocalDate publishDate; public static Book create(String isbn, String title, int price, LocalDate publishDate) { Book book = new Book(); book.setIsbn(isbn); book.setTitle(title); book.setPrice(price); book.setPublishDate(publishDate); return book; } // getterïŒsetterã¯çç¥ }
ãšããã©ããJacksonã®ã¢ãããŒã·ã§ã³ãå ¥ã£ãŠããŸãããå®éã®å©çšæã«çŽ¹ä»ããŸãã
CSVãã¡ã€ã«ãèªã¿èŸŒã
ãŸãã¯ãCSVãã¡ã€ã«ãèªã¿èŸŒãã§ã¿ãŸãããã
ãã¹ãã³ãŒãã®é圢ã
src/test/java/org/littlewings/jackson/csv/JacksonCsvReadTest.java
package org.littlewings.jackson.csv; import java.io.BufferedReader; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Paths; import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.stream.Collectors; import com.fasterxml.jackson.databind.MappingIterator; import com.fasterxml.jackson.dataformat.csv.CsvMapper; import com.fasterxml.jackson.dataformat.csv.CsvParser; import com.fasterxml.jackson.dataformat.csv.CsvSchema; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; import org.junit.jupiter.api.Test; public class JacksonCsvReadTest { // ããã«ããã¹ãã³ãŒããæžã }
ããã«ããã¹ãã³ãŒããåããŠããæ¹éãšããŸããããã¢ãµãŒã·ã§ã³ããŠãŸãããã©âŠã
Stringã®é åãšããŠèªã¿èŸŒãïŒããããŒããïŒ
æåã¯ãCSVãã¡ã€ã«ã®åã¬ã³ãŒããString
ã®é
åãšããŠèªã¿èŸŒã¿ãŸãã
ããã¥ã¡ã³ãã ãšããã®ãããã§ããã
CsvSchema / Column definitions / "Unmapped" (no columns)
ãããªæãã«ãªããŸããã
@Test public void readCsvWithHeaderAsStringArray() throws IOException { CsvMapper mapper = new CsvMapper(); CsvSchema schema = CsvSchema .emptySchema() .withoutHeader() .withSkipFirstDataRow(true) // 1ã¬ã³ãŒãç®ãé£ã°ã .withColumnSeparator(',') // default .withQuoteChar('"') // default .withEscapeChar('\\'); mapper.enable(CsvParser.Feature.WRAP_AS_ARRAY); try (BufferedReader reader = Files.newBufferedReader(Paths.get("src/test/resources/books.csv"), StandardCharsets.UTF_8)) { MappingIterator<String[]> iterator = mapper .readerFor(String[].class) .with(schema) .readValues(reader); while (iterator.hasNext()) { System.out.println(Arrays.stream(iterator.next()).collect(Collectors.joining(", "))); } } }
CsvMapper
ã®ã€ã³ã¹ã¿ã³ã¹ãäœããããããCsvSchema
ã®èšå®ãè¡ããŸãã
CsvMapper mapper = new CsvMapper(); CsvSchema schema = CsvSchema .emptySchema() .withoutHeader() .withSkipFirstDataRow(true) // 1ã¬ã³ãŒãç®ãé£ã°ã .withColumnSeparator(',') // default .withQuoteChar('"') // default .withEscapeChar('\\'); mapper.enable(CsvParser.Feature.WRAP_AS_ARRAY);
CsvSchema#emptySchema
ã§ããã©ã«ãã®ã¹ããŒãå®çŸ©ãè¿ãã®ã§ããããããŒã¹ã«å¿
èŠã«å¿ããŠèšå®ãå€ããŠãããŸãã
èªã¿èŸŒãCSVãã¡ã€ã«ã¯ããããŒãããªã®ã§ãããããããŒã®å€ãèªãã§ããã£ãŠãå°ãã®ã§ãããããŒãªãã
æåã®ã¬ã³ãŒããèªã¿é£ã°ãèšå®ã«ããŸããã
CsvParser.Feature.WRAP_AS_ARRAY
ã¯ãã¬ã³ãŒãã®æ§æèŠçŽ ãé
åãšããŠè¿ãã®ã§æå®ããŠããŸãããã®ä»ãList
ã«ããæãªã©ã«
䟿å©ãªããã§ãã
CsvParser.Feature (Jackson-dataformat-CSV 2.12.3 API)
CSVãã¡ã€ã«ã®èªã¿èŸŒã¿ãåã¬ã³ãŒãã®ååŸã¯ãããªæãã«ãªããŸãã
try (BufferedReader reader = Files.newBufferedReader(Paths.get("src/test/resources/books.csv"), StandardCharsets.UTF_8)) { MappingIterator<String[]> iterator = mapper .readerFor(String[].class) .with(schema) .readValues(reader); while (iterator.hasNext()) { System.out.println(Arrays.stream(iterator.next()).collect(Collectors.joining(", "))); } }
MappingIterator
ã¯ãJackson Databindã®ã¯ã©ã¹ã§ããã
èªã¿èŸŒã¿çµæã®Class
ã¯ã©ã¹ãã¹ããŒãå®çŸ©ãCSVãã¡ã€ã«ã®èªã¿èŸŒã¿å
ãæå®ããŠãCsvMapper
ããååŸããŸãã
MappingIterator<String[]> iterator =
mapper
.readerFor(String[].class)
.with(schema)
.readValues(reader);
ãã¡ãã䜿ã£ãŠãCSVãã¡ã€ã«ã1ã¬ã³ãŒããã€èªãã§ããããã«ããŸããã
å®è¡çµæã
978-4621303252, Effective Java 第3ç, 4400, 2018-10-30 978-4798151120, ç¬ç¿Java, 3278, 2019-05-15 978-4295008477, æ°äžä»£Javaããã°ã©ãã³ã°ã¬ã€ã[Java SE 10/11/12/13ãšèšèªæ¡åŒµãããžã§ã¯ã], 2860, 2020-03-13 978-4774189093, Javaæ¬æ Œå ¥é "ã¢ãã³ã¹ã¿ã€ã«ã«ããåºç€ãããªããžã§ã¯ãæåã»å®çšã©ã€ãã©ãªãŸã§", 3278, 2017-04-18 978-4774166858, æ¹èš2ç ããŒãã§ã¯ãJava, 3520, 2014-11-01
Stringã®é åãšããŠèªã¿èŸŒãïŒããããŒãªãïŒ
ããããŒãªãã®CSVãã¡ã€ã«ãèªã¿èŸŒã¿ãString
ã®é
åãšããŠåãåãå Žåã
@Test public void readCsvWithoutHeaderAsStringArray() throws IOException { CsvMapper mapper = new CsvMapper(); CsvSchema schema = CsvSchema .emptySchema() .withColumnSeparator(',') // default .withQuoteChar('"') // default .withEscapeChar('\\'); mapper.enable(CsvParser.Feature.WRAP_AS_ARRAY); try (BufferedReader reader = Files.newBufferedReader(Paths.get("src/test/resources/books_headerless.csv"), StandardCharsets.UTF_8)) { MappingIterator<String[]> iterator = mapper .readerFor(String[].class) .with(schema) .readValues(reader); while (iterator.hasNext()) { System.out.println(Arrays.stream(iterator.next()).collect(Collectors.joining(", "))); } } }
å ã»ã©ãšã®éãã¯ãããããŒãªããæåã®ã¬ã³ãŒãã®èªã¿é£ã°ããæ¶ããã ãã§ããã
ãããããããã©ã«ããããããŒãªããªã®ã§âŠã
å®è¡çµæã¯ããã¡ãã
978-4621303252, Effective Java 第3ç, 4400, 2018-10-30 978-4798151120, ç¬ç¿Java, 3278, 2019-05-15 978-4295008477, æ°äžä»£Javaããã°ã©ãã³ã°ã¬ã€ã[Java SE 10/11/12/13ãšèšèªæ¡åŒµãããžã§ã¯ã], 2860, 2020-03-13 978-4774189093, Javaæ¬æ Œå ¥é "ã¢ãã³ã¹ã¿ã€ã«ã«ããåºç€ãããªããžã§ã¯ãæåã»å®çšã©ã€ãã©ãªãŸã§", 3278, 2017-04-18 978-4774166858, æ¹èš2ç ããŒãã§ã¯ãJava, 3520, 2014-11-01
MapãšããŠèªã¿èŸŒãïŒããããŒããïŒ
次ã«ãåã¬ã³ãŒããMap
ãšããŠèªã¿èŸŒãã§ã¿ãŸãããããããããšãããããŒã®å
容ãMap
ã®ããŒãšããŠæ±ã£ãŠãããŸãã
ãã¡ãã®å 容ã§ããã
With column names from first row
@Test public void readCsvWithHeaderAsMap() throws IOException { CsvMapper mapper = new CsvMapper(); CsvSchema schema = CsvSchema .emptySchema() .withHeader() // 1ã¬ã³ãŒãç®ãããããŒãšããŠäœ¿ã .withColumnSeparator(',') // default .withQuoteChar('"') // default .withEscapeChar('\\'); try (BufferedReader reader = Files.newBufferedReader(Paths.get("src/test/resources/books.csv"), StandardCharsets.UTF_8)) { MappingIterator<Map<String, String>> iterator = mapper .readerFor(Map.class) .with(schema) .readValues(reader); while (iterator.hasNext()) { System.out.println( iterator.next().entrySet().stream().map(e -> e.getKey() + ":" + e.getValue()).collect(Collectors.joining(", ")) ); } } }
ãªã®ã§ãããããŒãèªèããããã«èšå®ãCsvParser.Feature.WRAP_AS_ARRAY
ã¯äžèŠã«ãªããŸãã
CsvMapper mapper = new CsvMapper(); CsvSchema schema = CsvSchema .emptySchema() .withHeader() // 1ã¬ã³ãŒãç®ãããããŒãšããŠäœ¿ã .withColumnSeparator(',') // default .withQuoteChar('"') // default .withEscapeChar('\\');
CsvMapper#readerFor
ã«ã¯ãMap
ã®Class
ã¯ã©ã¹ãæå®ã
MappingIterator<Map<String, String>> iterator =
mapper
.readerFor(Map.class)
.with(schema)
.readValues(reader);
çµæã¯ãã¡ãã
isbn:978-4621303252, title:Effective Java 第3ç, price:4400, publishDate:2018-10-30 isbn:978-4798151120, title:ç¬ç¿Java, price:3278, publishDate:2019-05-15 isbn:978-4295008477, title:æ°äžä»£Javaããã°ã©ãã³ã°ã¬ã€ã[Java SE 10/11/12/13ãšèšèªæ¡åŒµãããžã§ã¯ã], price:2860, publishDate:2020-03-13 isbn:978-4774189093, title:Javaæ¬æ Œå ¥é "ã¢ãã³ã¹ã¿ã€ã«ã«ããåºç€ãããªããžã§ã¯ãæåã»å®çšã©ã€ãã©ãªãŸã§", price:3278, publishDate:2017-04-18 isbn:978-4774166858, title:æ¹èš2ç ããŒãã§ã¯ãJava, price:3520, publishDate:2014-11-01
MapãšããŠèªã¿èŸŒãïŒããããŒãªãïŒ
ä»åºŠã¯ãããããŒãªãã®CSVãã¡ã€ã«ãèªã¿ãMap
ãšããŠåãåããŸãã
@Test public void readCsvWithoutHeaderAsMap() throws IOException { CsvMapper mapper = new CsvMapper(); CsvSchema schema = CsvSchema .builder() .addColumns(List.of("isbn", "title", "price", "publishDate"), CsvSchema.ColumnType.STRING) // ã«ã©ã ãå®çŸ© .setColumnSeparator(',') // default .setQuoteChar('"') // default .setEscapeChar('\\') .build(); try (BufferedReader reader = Files.newBufferedReader(Paths.get("src/test/resources/books_headerless.csv"), StandardCharsets.UTF_8)) { MappingIterator<Map<String, String>> iterator = mapper .readerFor(Map.class) .with(schema) .readValues(reader); while (iterator.hasNext()) { System.out.println( iterator.next().entrySet().stream().map(e -> e.getKey() + ":" + e.getValue()).collect(Collectors.joining(", ")) ); } } }
å€ãã£ããã€ã³ããšããŠã¯ãCsvSchema
ã®äœãæ¹ã§ãããããããŒããªãã®ã§ãããŒã®ååãã«ã©ã ãšããŠå®çŸ©ããå¿
èŠã
ãããŸãã
CsvSchema schema = CsvSchema .builder() .addColumns(List.of("isbn", "title", "price", "publishDate"), CsvSchema.ColumnType.STRING) // ã«ã©ã ãå®çŸ© .setColumnSeparator(',') // default .setQuoteChar('"') // default .setEscapeChar('\\') .build();
å€ãã£ãã®ã¯ããããããã§ããã
çµæã
isbn:978-4621303252, title:Effective Java 第3ç, price:4400, publishDate:2018-10-30 isbn:978-4798151120, title:ç¬ç¿Java, price:3278, publishDate:2019-05-15 isbn:978-4295008477, title:æ°äžä»£Javaããã°ã©ãã³ã°ã¬ã€ã[Java SE 10/11/12/13ãšèšèªæ¡åŒµãããžã§ã¯ã], price:2860, publishDate:2020-03-13 isbn:978-4774189093, title:Javaæ¬æ Œå ¥é "ã¢ãã³ã¹ã¿ã€ã«ã«ããåºç€ãããªããžã§ã¯ãæåã»å®çšã©ã€ãã©ãªãŸã§", price:3278, publishDate:2017-04-18 isbn:978-4774166858, title:æ¹èš2ç ããŒãã§ã¯ãJava, price:3520, publishDate:2014-11-01
èªåã§å®çŸ©ããã¯ã©ã¹ã§èªã¿èŸŒãïŒããããŒããïŒ
èªã¿èŸŒã¿ç³»ã®æåŸã¯ãèªåã§å®çŸ©ããã¯ã©ã¹ã§èªã¿èŸŒãããã«ããŠã¿ãŸãã
ãœãŒã¹ã³ãŒãã¯ããããªæãã«ã
@Test public void readCsvWithHeaderAsClass() throws IOException { CsvMapper mapper = new CsvMapper(); mapper.registerModules(new JavaTimeModule()); // for LocalDate / LocalDateTime CsvSchema schema = mapper .schemaFor(Book.class) .withHeader() .withColumnSeparator(',') // default .withQuoteChar('"') // default .withEscapeChar('\\'); try (BufferedReader reader = Files.newBufferedReader(Paths.get("src/test/resources/books.csv"), StandardCharsets.UTF_8)) { MappingIterator<Book> iterator = mapper .readerFor(Book.class) .with(schema) .readValues(reader); while (iterator.hasNext()) { Book book = iterator.next(); System.out.printf("isbn: %s, title: %s, price: %d, publishDate: %s%n", book.getIsbn(), book.getTitle(), book.getPrice(), book.getPublishDate()); } } }
ãããªãè±ç·ããŸããããããã³ã°å
ã®ã¯ã©ã¹ããããªæãã§LocalDate
ã䜿ã£ãŠããã®ã§
@JsonPropertyOrder({"isbn", "title", "price", "publishDate"}) // for CsvMapper#schemaFor public class Book { String isbn; String title; int price; @JsonFormat(pattern = "yyyy-MM-dd") LocalDate publishDate;
CsvMapper
ã«JavaTimeModule
ãç»é²ããŸãã
mapper.registerModules(new JavaTimeModule()); // for LocalDate / LocalDateTime
MappingIterator
ãããã®äœ¿ãæ¹ã¯å€ãããŸããããCsvSchema
ã®äœãæ¹ãå°ãå€ãããŸããä»åã¯ãCsvMapper#schemaFor
ã
䜿ããŸãã
CsvSchema schema = mapper .schemaFor(Book.class) .withHeader() .withColumnSeparator(',') // default .withQuoteChar('"') // default .withEscapeChar('\\');
ããã§æå®ããã¯ã©ã¹ãã¹ããŒãã®å
ã«ãªãã®ã§ããã察象ã®ã¯ã©ã¹ã«ã¯@JsonPropertyOrder
ã¢ãããŒã·ã§ã³ã§
ããããã£ã®é ãæå®ããŠããå¿
èŠããããŸãã
@JsonPropertyOrder({"isbn", "title", "price", "publishDate"}) // for CsvMapper#schemaFor public class Book {
泚æç¹ã¯ããã®ãããã§ããã
çµæã
isbn: 978-4621303252, title: Effective Java 第3ç, price: 4400, publishDate: 2018-10-30 isbn: 978-4798151120, title: ç¬ç¿Java, price: 3278, publishDate: 2019-05-15 isbn: 978-4295008477, title: æ°äžä»£Javaããã°ã©ãã³ã°ã¬ã€ã[Java SE 10/11/12/13ãšèšèªæ¡åŒµãããžã§ã¯ã], price: 2860, publishDate: 2020-03-13 isbn: 978-4774189093, title: Javaæ¬æ Œå ¥é "ã¢ãã³ã¹ã¿ã€ã«ã«ããåºç€ãããªããžã§ã¯ãæåã»å®çšã©ã€ãã©ãªãŸã§", price: 3278, publishDate: 2017-04-18 isbn: 978-4774166858, title: æ¹èš2ç ããŒãã§ã¯ãJava, price: 3520, publishDate: 2014-11-01
èªåã§å®çŸ©ããã¯ã©ã¹ã§èªã¿èŸŒãïŒããããŒãªãïŒ
ããããŒãªãã®å Žåã¯ããã¡ãã
@Test public void readCsvWithoutHeaderAsClass() throws IOException { CsvMapper mapper = new CsvMapper(); mapper.registerModules(new JavaTimeModule()); // for LocalDate / LocalDateTime CsvSchema schema = mapper .schemaFor(Book.class) .withoutHeader() .withSkipFirstDataRow(true) // 1ã¬ã³ãŒãç®ãé£ã°ã .withColumnSeparator(',') // default .withQuoteChar('"') // default .withEscapeChar('\\'); try (BufferedReader reader = Files.newBufferedReader(Paths.get("src/test/resources/books.csv"), StandardCharsets.UTF_8)) { MappingIterator<Book> iterator = mapper .readerFor(Book.class) .with(schema) .readValues(reader); while (iterator.hasNext()) { Book book = iterator.next(); System.out.printf("isbn: %s, title: %s, price: %d, publishDate: %s%n", book.getIsbn(), book.getTitle(), book.getPrice(), book.getPublishDate()); } } }
ãããããŠèª¬æããªããå 容ã¯ãªãã®ã§ãå²æã
çµæã
isbn: 978-4621303252, title: Effective Java 第3ç, price: 4400, publishDate: 2018-10-30 isbn: 978-4798151120, title: ç¬ç¿Java, price: 3278, publishDate: 2019-05-15 isbn: 978-4295008477, title: æ°äžä»£Javaããã°ã©ãã³ã°ã¬ã€ã[Java SE 10/11/12/13ãšèšèªæ¡åŒµãããžã§ã¯ã], price: 2860, publishDate: 2020-03-13 isbn: 978-4774189093, title: Javaæ¬æ Œå ¥é "ã¢ãã³ã¹ã¿ã€ã«ã«ããåºç€ãããªããžã§ã¯ãæåã»å®çšã©ã€ãã©ãªãŸã§", price: 3278, publishDate: 2017-04-18 isbn: 978-4774166858, title: æ¹èš2ç ããŒãã§ã¯ãJava, price: 3520, publishDate: 2014-11-01
CSVãã¡ã€ã«ãæžã蟌ã
次ã¯ãCSVãã¡ã€ã«ã®æžã蟌ã¿ãè¡ã£ãŠã¿ãŸãããã
ãã¹ãã³ãŒãã®é圢ã¯ãã¡ãã
src/test/java/org/littlewings/jackson/csv/JacksonCsvWriteTest.java
package org.littlewings.jackson.csv; import java.io.BufferedWriter; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Paths; import java.time.LocalDate; import java.util.List; import com.fasterxml.jackson.databind.SequenceWriter; import com.fasterxml.jackson.dataformat.csv.CsvMapper; import com.fasterxml.jackson.dataformat.csv.CsvSchema; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; import org.junit.jupiter.api.Test; public class JacksonCsvWriteTest { String[][] booksArray = { {"978-4621303252", "Effective Java 第3ç", "4400", "2018-10-30"}, {"978-4798151120", "ç¬ç¿Java", "3278", "2019-05-15"}, {"978-4295008477", "æ°äžä»£Javaããã°ã©ãã³ã°ã¬ã€ã[Java SE 10/11/12/13ãšèšèªæ¡åŒµãããžã§ã¯ã]", "2860", "2020-03-13"}, {"978-4774189093", "Javaæ¬æ Œå ¥é \"ã¢ãã³ã¹ã¿ã€ã«ã«ããåºç€ãããªããžã§ã¯ãæåã»å®çšã©ã€ãã©ãªãŸã§\"", "3278", "2017-04-18"}, {"978-4774166858", "æ¹èš2ç ããŒãã§ã¯ãJava", "3520", "2014-11-01"} }; List<Book> books = List.of( Book.create("978-4621303252", "Effective Java 第3ç", 4400, LocalDate.of(2018, 10, 30)), Book.create("978-4798151120", "ç¬ç¿Java", 3278, LocalDate.of(2019, 5, 15)), Book.create("978-4295008477", "æ°äžä»£Javaããã°ã©ãã³ã°ã¬ã€ã[Java SE 10/11/12/13ãšèšèªæ¡åŒµãããžã§ã¯ã]", 2860, LocalDate.of(2020, 3, 13)), Book.create("978-4774189093", "Javaæ¬æ Œå ¥é \"ã¢ãã³ã¹ã¿ã€ã«ã«ããåºç€ãããªããžã§ã¯ãæåã»å®çšã©ã€ãã©ãªãŸã§\"", 3278, LocalDate.of(2017, 4, 18)), Book.create("978-4774166858", "æ¹èš2ç ããŒãã§ã¯ãJava", 3520, LocalDate.of(2014, 11, 1)) ); // ããã«ããã¹ããæžã }
CSVãã¡ã€ã«ã«æžã蟌ãèŠçŽ ã¯ãäºåã«ãã£ãŒã«ãã«å®çŸ©ããŠããããšã«ããŸããã
ã§ã¯ãåçš®ã³ãŒããåããŠãããŸãã
Stringã®é åãæžã蟌ãïŒããããŒããïŒ
ãŸãã¯ãString
ã®é
åãšããŠæžã蟌ããã¿ãŒã³ãããããããŒããã§ãã
ãœãŒã¹ã³ãŒãã¯ããããªæãã«ãªããŸããã
@Test public void writeCsvWithHeaderAsStringArray() throws IOException { CsvMapper mapper = new CsvMapper(); CsvSchema schema = CsvSchema .builder() .addColumns(List.of("isbn", "title", "price", "publishDate"), CsvSchema.ColumnType.STRING) // ã«ã©ã ãå®çŸ© .setUseHeader(true) // print header .setColumnSeparator(',') // default .setQuoteChar('"') // default .build(); try (BufferedWriter writer = Files.newBufferedWriter(Paths.get("target/books_from_array.csv"), StandardCharsets.UTF_8)) { SequenceWriter sequenceWriter = mapper .writerFor(String[].class) .with(schema) .writeValues(writer); for (String[] values : booksArray) { sequenceWriter.write(values); } } }
CsvSchema
ã®äœãæ¹ã¯èªã¿èŸŒã¿æãšããå€ãããŸããããããããŒãäœãåã ãã«ã©ã å®çŸ©ãå¿
èŠã«ãªããŸãã
CsvMapper mapper = new CsvMapper(); CsvSchema schema = CsvSchema .builder() .addColumns(List.of("isbn", "title", "price", "publishDate"), CsvSchema.ColumnType.STRING) // ã«ã©ã ãå®çŸ© .setUseHeader(true) // print header .setColumnSeparator(',') // default .setQuoteChar('"') // default .build();
ãŸããCsvParser.Feature.WRAP_AS_ARRAY
ã¯äžèŠã§ãã
æžã蟌ã¿ã«ã¯ãSequenceWriter
ã䜿ãã1ã¬ã³ãŒããã€æžã蟌ãã§ãããŸãã
try (BufferedWriter writer = Files.newBufferedWriter(Paths.get("target/books_from_array.csv"), StandardCharsets.UTF_8)) { SequenceWriter sequenceWriter = mapper .writerFor(String[].class) .with(schema) .writeValues(writer); for (String[] values : booksArray) { sequenceWriter.write(values); } }
çµæã¯ãã¡ãã
target/books_from_array.csv
isbn,title,price,publishDate 978-4621303252,"Effective Java 第3ç",4400,2018-10-30 978-4798151120,ç¬ç¿Java,3278,2019-05-15 978-4295008477,"æ°äžä»£Javaããã°ã©ãã³ã°ã¬ã€ã[Java SE 10/11/12/13ãšèšèªæ¡åŒµãããžã§ã¯ã]",2860,2020-03-13 978-4774189093,"Javaæ¬æ Œå ¥é ""ã¢ãã³ã¹ã¿ã€ã«ã«ããåºç€ãããªããžã§ã¯ãæåã»å®çšã©ã€ãã©ãªãŸã§""",3278,2017-04-18 978-4774166858,"æ¹èš2ç ããŒãã§ã¯ãJava",3520,2014-11-01
ããããŒãåºåãããŠããŸãã
å²ã¿æåã®ãšã¹ã±ãŒãã¯ãå²ã¿æåã2ã€éããããšã§è¡ããŸããèªã¿èŸŒã¿æãšéãããã¡ãã¯èšå®ãã§ããŸããã
Stringã®é åãæžã蟌ãïŒããããŒãªãïŒ
ããããŒãªãã®å Žåã
@Test public void writeCsvWithoutHeaderAsStringArray() throws IOException { CsvMapper mapper = new CsvMapper(); CsvSchema schema = CsvSchema .emptySchema() .withColumnSeparator(',') // default .withQuoteChar('"'); // default try (BufferedWriter writer = Files.newBufferedWriter(Paths.get("target/books_from_array_headerless.csv"), StandardCharsets.UTF_8)) { SequenceWriter sequenceWriter = mapper .writerFor(String[].class) .with(schema) .writeValues(writer); for (String[] values : booksArray) { sequenceWriter.write(values); } } }
ããããŒããªãã®ã§ããããã·ã³ãã«ã«ãªããŸãã
çµæã¯ããã¡ãã
target/books_from_array_headerless.csv
978-4621303252,"Effective Java 第3ç",4400,2018-10-30 978-4798151120,ç¬ç¿Java,3278,2019-05-15 978-4295008477,"æ°äžä»£Javaããã°ã©ãã³ã°ã¬ã€ã[Java SE 10/11/12/13ãšèšèªæ¡åŒµãããžã§ã¯ã]",2860,2020-03-13 978-4774189093,"Javaæ¬æ Œå ¥é ""ã¢ãã³ã¹ã¿ã€ã«ã«ããåºç€ãããªããžã§ã¯ãæåã»å®çšã©ã€ãã©ãªãŸã§""",3278,2017-04-18 978-4774166858,"æ¹èš2ç ããŒãã§ã¯ãJava",3520,2014-11-01
èªåã§å®çŸ©ããã¯ã©ã¹ã§æžã蟌ãïŒããããŒããïŒ
æåŸã¯ãèªåã§å®çŸ©ããã¯ã©ã¹ã§æžã蟌ãå Žåã§ãããŸãã¯ãããããŒããã®å Žåããã
@Test public void writeCsvWithHeaderAsClass() throws IOException { CsvMapper mapper = new CsvMapper(); mapper.registerModules(new JavaTimeModule()); // for LocalDate / LocalDateTime CsvSchema schema = mapper .schemaFor(Book.class) .withHeader() // print header .withColumnSeparator(',') // default .withQuoteChar('"'); // default try (BufferedWriter writer = Files.newBufferedWriter(Paths.get("target/books.csv"), StandardCharsets.UTF_8)) { SequenceWriter sequenceWriter = mapper .writerFor(Book.class) .with(schema) .writeValues(writer); for (Book book : books) { sequenceWriter.write(book); } } }
ãšãã£ãŠãããããŸã§æ¥ããšæ¬åœã«ç®æ°ããèŠçŽ ã¯ãªãã§ããâŠã
èªã¿èŸŒã¿æãšåãããCsvMapper#schemaFor
ã§å¯Ÿè±¡ã®Class
ã¯ã©ã¹ãæå®ããŸãã
CsvSchema schema = mapper .schemaFor(Book.class) .withHeader() // print header .withColumnSeparator(',') // default .withQuoteChar('"'); // default
çµæãããããŒããã§ãã
target/books.csv
isbn,title,price,publishDate 978-4621303252,"Effective Java 第3ç",4400,2018-10-30 978-4798151120,ç¬ç¿Java,3278,2019-05-15 978-4295008477,"æ°äžä»£Javaããã°ã©ãã³ã°ã¬ã€ã[Java SE 10/11/12/13ãšèšèªæ¡åŒµãããžã§ã¯ã]",2860,2020-03-13 978-4774189093,"Javaæ¬æ Œå ¥é ""ã¢ãã³ã¹ã¿ã€ã«ã«ããåºç€ãããªããžã§ã¯ãæåã»å®çšã©ã€ãã©ãªãŸã§""",3278,2017-04-18 978-4774166858,"æ¹èš2ç ããŒãã§ã¯ãJava",3520,2014-11-01
èªåã§å®çŸ©ããã¯ã©ã¹ã§æžã蟌ãïŒããããŒãªãïŒ
ããããŒãªãã®å Žåãããã£ãšã
@Test public void writeCsvWithoutHeaderAsClass() throws IOException { CsvMapper mapper = new CsvMapper(); mapper.registerModules(new JavaTimeModule()); // for LocalDate / LocalDateTime CsvSchema schema = mapper .schemaFor(Book.class) .withColumnSeparator(',') // default .withQuoteChar('"'); // default try (BufferedWriter writer = Files.newBufferedWriter(Paths.get("target/books_headerless.csv"), StandardCharsets.UTF_8)) { SequenceWriter sequenceWriter = mapper .writerFor(Book.class) .with(schema) .writeValues(writer); for (Book book : books) { sequenceWriter.write(book); } } }
çµæã
target/books_headerless.csv
978-4621303252,"Effective Java 第3ç",4400,2018-10-30 978-4798151120,ç¬ç¿Java,3278,2019-05-15 978-4295008477,"æ°äžä»£Javaããã°ã©ãã³ã°ã¬ã€ã[Java SE 10/11/12/13ãšèšèªæ¡åŒµãããžã§ã¯ã]",2860,2020-03-13 978-4774189093,"Javaæ¬æ Œå ¥é ""ã¢ãã³ã¹ã¿ã€ã«ã«ããåºç€ãããªããžã§ã¯ãæåã»å®çšã©ã€ãã©ãªãŸã§""",3278,2017-04-18 978-4774166858,"æ¹èš2ç ããŒãã§ã¯ãJava",3520,2014-11-01
ãŸãšã
Jackson Text Dataformats Moduleã䜿ã£ãŠãCSVãã¡ã€ã«ãèªã¿æžãããŠã¿ãŸããã
JacksonãããŒã¹ã«ãªã£ãŠããã ããã£ãŠãä»ã®CSVé¢ä¿ã®ã©ã€ãã©ãªãšã¡ãã£ãšå€ãã£ãŠããæããããŸãããé«éãªããã§ãã
Jacksonèªäœããã䜿ããšæãã®ã§ãèŠããŠãããŠãããã§ãããã