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?
You have several mistakes in your code.
asJsObject()
is a method that does not exist in JsValue
. Instead you should use value.as[JsObject]
.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
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:
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.