Ruchir Dixit
Ruchir Dixit

Reputation: 125

Creating csv file in Scala

I am trying to to create a csv file in Scala by getting data in the form of JsValue from a third part API. My method to save data to CSV file is :

def saveToCSV(str:Seq[JsValue]) = {
  val outputFile = new BufferedWriter(new FileWriter("Result.csv"))
  val csvWriter = new CSVWriter(outputFile)
    val data = str.head
    data match {
      case JsObject(fields) => {
        var listOfRecords = new ListBuffer[Array[String]]()
        //val csvFields = Array("Open","High","Low","Close","Volume")
        //listOfRecords += csvFields
        fields.values.foreach(value => {
          val jsObject = value.asJsObject()
          val nameList = List(jsObject.fields("1. open").toString,jsObject.fields("2. high").toString,jsObject.fields("3. low").toString,jsObject.fields("4. close").toString,jsObject.fields("5. volume").toString)
          listOfRecords += Array(nameList.toString)
          csvWriter.writeAll(listOfRecords.toList.asInstanceOf)
          println("Written!")
          outputFile.close()
        })
      }
      case JsNull => println("Null")
    }

In the above code on line **csvWriter.writeAll(listOfRecords.toList.asInstanceOf)** I am getting this exception.

Exception in thread "main" java.lang.ClassCastException: class scala.collection.immutable.$colon$colon cannot be cast to class scala.runtime.Nothing$ (scala.collection.immutable.$colon$colon and scala.runtime.Nothing$ are in unnamed module of loader 'app')

On removing asInstanceOf from csvWriter.writeAll(listOfRecords.toList.asInstanceOf) this line, I get a compile time error on writeAll() method saying that it expects parameter of type util.List[Array[String]]

Could anyone please help me to solve this problem?

Upvotes: 0

Views: 1750

Answers (1)

Tomer Shetah
Tomer Shetah

Reputation: 8539

You have several mistakes in your code.

  1. asJsObject() is a method that does not exist in JsValue. Instead you should use value.as[JsObject].
  2. jsObject.fields is of type Seq[(String, JsValue)], so you can't call jsObject.fields("1. open"). Instead you should call: jsObject("1. open").toString
  3. Calling listOfRecords.toList.asInstanceOf returns null. You should specify what you want to convert it to. But in order to convert it into a java type, you can just call: listOfRecords.toList.asJava. Don't forget: import scala.jdk.CollectionConverters._

The complete method is:

import com.opencsv.CSVWriter
import play.api.libs.json.{JsNull, JsObject, JsValue}

import java.io.{BufferedWriter, FileWriter}
import scala.collection.mutable.ListBuffer
import scala.jdk.CollectionConverters._

def saveToCSV(str: Seq[JsValue]) = {
  val outputFile = new BufferedWriter(new FileWriter("Result.csv"))
  val csvWriter = new CSVWriter(outputFile)
  val data = str.head
  data match {
    case JsObject(fields) => {
      var listOfRecords = new ListBuffer[Array[String]]()
      //val csvFields = Array("Open","High","Low","Close","Volume")
      //listOfRecords += csvFields
      fields.values.foreach(value => {
        val jsObject = value.as[JsObject]
        val nameList = List(jsObject("1. open").toString, jsObject("2. high").toString, jsObject("3. low").toString, jsObject("4. close").toString, jsObject("5. volume").toString)
        listOfRecords += Array(nameList.toString)
        csvWriter.writeAll(listOfRecords.toList.asJava)
        println("Written!")
        outputFile.close()
      })
    }
    case JsNull => println("Null")
  }
}

This will work under the assumption that the head of str contains a JsObject, with the fields:

  • "1. open"
  • "2. high"
  • "3. low"
  • "4. close"

Are you deliberately taking only the first element of the input to this function? Please note that str.head is unsafe, in case the sequence is empty.

Upvotes: 1

Related Questions