Soumya Simanta
Soumya Simanta

Reputation: 11751

Converting a case class to CSV in Scala

Is there a elegant way to convert a case class to a CSV value.

For example -

 case class Person( name : String, age : Int, gender: String, address : Option[String])

I was thinking about using macros but would like to know if there are any other alternatives.

NOTE: The case class doesn't contain any user defined fields.

Upvotes: 9

Views: 8542

Answers (4)

Loic
Loic

Reputation: 3370

To complete the accepted answer, you can also match the Product type with pattern matching :

implicit class CSVWrapper(val prod: Product) extends AnyVal {
  def toCSV: String = prod.productIterator.map{
    case p: Product =>  p.toCSV
    case rest => rest
  }.mkString(",")
}

This would work with embedded case classes :

case class Address(street: String, town: String, country: Option[String])
case class Person( name : String, age : Int, gender: Option[String], address : Option[Address])

Person("myname", 30, Some("male"), Some(Address("mystreet", "city", None))).toCSV
// result :
// myname,30,male,mystreet,city,

Upvotes: 0

Mark Lister
Mark Lister

Reputation: 1143

product-collections will also produce csv for you. product-collections scales pretty well; it's reflection free & compatible with scala-js.

import com.github.marklister.collections.io._
case class Foo(a:Int,b:String)
Seq(Foo(1,"hello"),Foo(2,"World")).csvIterator.mkString("\n")

res2: String =
1,"hello"
2,"World"

I'm the author of product-collections

Upvotes: 2

mariop
mariop

Reputation: 3226

Yes, in Scala there is a way to convert a case class to CSV without adding boilerplate at all. For instance PureCSV, based on the amazing Shapeless library, can do it:

scala> import purecsv.safe._
scala> case class Interval(start: Long, end: Long)
scala> Interval(10,20).toCSV()
res1: String = 1,10
scala> Seq(Interval(1,10),Interval(11,20)).toCSV("|")
res2: String =
1|10
11|20

Note: I'm the author of PureCSV.

Upvotes: 11

Justin Pihony
Justin Pihony

Reputation: 67115

How about implicits and productIterator?

implicit class CSVWrapper(val prod: Product) extends AnyVal {
    def toCSV() = prod.productIterator.map{
                    case Some(value) => value
                    case None => ""
                    case rest => rest
                  }.mkString(",")
}

Person("name", 30, "male", None).toCSV()

Upvotes: 17

Related Questions