piotr-kalanski / csv2class

CSV reader/writer with conversion to Scala case class

GitHub

csv2class

Generic CSV reader/writer with conversion to Scala case class without boilerplate

Build Status codecov.io License

Table of contents

Goals

  • Read and convert CSV files to Scala case classes
  • Write Scala case classes to CSV

Getting started

Include dependency:

"com.github.piotr-kalanski" % "csv2class_2.11" % "0.3.3"

or

<dependency>
    <groupId>com.github.piotr-kalanski</groupId>
    <artifactId>csv2class_2.11</artifactId>
    <version>0.3.3</version>
</dependency>

For reading from CSV import:

import com.datawizards.csv2class._

For writing to CSV import:

import com.datawizards.class2csv._

Examples

Reading from CSV

Basic example:

CSV file:

s,i
first,10
second,11

Parsing command:

case class Foo(s: String, i: Int)
parseCSV[Foo]("foo.csv")

result:

Foo("first",10),
Foo("second",11)

Different order of columns

CSV file:

i,s
10,first
11,second

Parsing command:

parseCSV[Foo]("foo.csv")

result:

Foo("first",10),
Foo("second",11)

Returning not parsed rows

CSV file:

s,i
first,10
second,11
third,third
parseCSV[Foo]("foo.csv")

result:

Foo(first,10)
Foo(second,11)
java.lang.NumberFormatException: For input string: "third"

Writing to CSV

case class Foo(s: String, i: Int)

val data = Seq(
  Foo("first",10),
  Foo("second",11)
)

writeCSV(data, file)

Versioning support

First write below data to CSV:

case class PersonV2(name: String, age: Int, title: Option[String])
val peopleV2 = Seq(
    PersonV2("p1", 10, Some("Developer")),
    PersonV2("p2", 20, None),
    PersonV2("p3", 30, None)
)
writeCSV(peopleV2, file)

Read CSV file with previous version of compatible Person model:

case class Person(name: String, age: Int)
parseCSV[Person](file)

result:

Seq(
  Person("p1", 10),
  Person("p2", 20),
  Person("p3", 30)
)

Read CSV file using newer compatible Person model version - new columns should be Option type.

case class PersonV3(name: String, age: Int, title: Option[String], salary: Option[Long])
parseCSV[PersonV3](file)

result:

Seq(
  PersonV3("p1", 10, Some("Developer"), None),
  PersonV3("p2", 20, None, None),
  PersonV3("p3", 30, None, None)
)

Complex types

Library supports writing fields with complex types (e.g. case class, Seq) by serializing them usin JSON format.

Example:

case class ClassWithArrayOfStruct(
  id: String,
  people: Seq[Person]
)
case class Person(name: String, age: Int)

val data = Seq(
  ClassWithArrayOfStruct("1",Seq(Person("p1", 10))),
  ClassWithArrayOfStruct("2",Seq(Person("p1", 10),Person("p2", 20),Person("p3", 30)))
)

writeCSV(data, file)

result:

id,people
1,"[{""name"":""p1"",""age"":10}]"
2,"[{""name"":""p1"",""age"":10},{""name"":""p2"",""age"":20},{""name"":""p3"",""age"":30}]"

Customizations

Change delimiter

parseCSV[Foo]("file.csv", delimiter = ';')
writeCSV(data, file, delimiter = ';')

CSV without header

parseCSV[Foo]("file.csv", header = false, columns = Seq("s","i"))
writeCSV(data, "file.csv", header = false)