samba
samba

Reputation: 3091

Scala - parse JSON data from API with ScalaJson Play Framework

First I have implemented a method to build a Map[Double, String] from a csv file. The map contains (k,v) of saleId, saleType. Here is how I've implemented this:

val stream : InputStream = getClass.getResourceAsStream("/sales.csv")
  val lines: Iterator[String] = scala.io.Source.fromInputStream(stream).getLines
  val map: Map[Double, String] = lines
    .map(_.split(","))
    .map(line => (line(0).toDouble, line(1).toString))
    .toMap

Now I want to go further and get data for building a map with data from API. With the same k,v (saleId, saleType). Json returned by API contains this data as fields.

Json look like this:

   [{ 
    "saleId": 1234, 
    "name": "New name", 
    "saleType": "New Type"
    }, 
    { 
    "saleId": 2345, 
    "name": "New name1", 
    "saleType": "New Type1" 
   }]

So I tried the approach using ScalaJson Play Framework. Since I only need two fields from JSON I decided to use a case class SalesData.

object SalesProcessor {
    case class SalesData(saleId: Int, saleType: String)
    implicit val of: Reads[SalesData] = reads[SalesData]

      val rawJson: String = Source.fromURL("https://mytest.com/api/sales.json").mkString
      val salesJson: JsValue = Json.parse(rawJson)
      val salesData: SalesData = salesJson.as[SalesData]

    def main(args: Array[String]): Unit = {
        println(salesData.saleId)
    }

When I run the above code I'm getting the following error:

play.api.libs.json.JsResultException: JsResultException(errors:List((,List(JsonValidationError(List(error.expected.jsobject),WrappedArray())))))

UPD: After I've used a solution proposed by tea-addict it started failing with the following error:

JsResultException(errors:List((/saleId,List(JsonValidationError(List(error.path.missing),WrappedArray()))), (/saleType,List(JsonValidationError(List(error.path.missing),WrappedArray())))))

Upvotes: 2

Views: 875

Answers (1)

earlymorningtea
earlymorningtea

Reputation: 508

You can read specific fields and create your SalesData like this.

Sales.json

[{ 
  "saleId": 1234, 
  "name": "New name", 
  "saleType": "New Type"
}, 
{ 
  "saleId": 2345, 
  "name": "New name1", 
  "saleType": "New Type1" 
 }]

Code

object SalesProcessor {
    case class SalesData(saleId: Int, saleType: String)
    implicit val saleReads: Reads[SalesData] = (
        (JsPath \ "saleId").read[Int] and
        (JsPath \ "saleType").read[String]
    ) (SalesData.apply _)

    val rawJson: String = Source.fromURL("https://mytest.com/api/sales.json").mkString
    val salesJson: JsValue = Json.parse(rawJson)
    val salesData: List[SalesData] = salesJson.as[List[SalesData]]

    def main(args: Array[String]): Unit = {
        println(salesData(0).saleId)
    }
}

Upvotes: 1

Related Questions