-2

I have a json data as

{"query":{"count":1,"created":"2014-04-28T07:33:09Z","lang":"en-US","results":{"rate":{"id":"USDCNY","Rate":"6.2489","Date":"4/28/2014","Time":"3:30am","Ask":"6.2494","Bid":"6.2484"}}}}

from above.,

I am interested only in

{"id":"USDCNY","Rate":"6.2489","Date":"4/28/2014","Time":"3:30am","Ask":"6.2494","Bid":"6.2484"}

data

I extracted it as a Map,

  val translateAPI = url(yahooFinanceApiUrl)
  val response = Http(translateAPI OK as.String)

  response onComplete {
    case Success(json) => parser(json)
    case Failure(error) => println(" Error " +error)
  }


  def parser(data:String) = {

    val languages = JSON.parseFull(data) match {
     case Some(x:Map[String, Map[String, Map[String, Any]]]) => {
     (x.get("query")).last.get("results").last.get("rate").last
   }
  case None => Nil
}

println(languages)

}

I got output as follows

Map(Rate -> 6.2532, Ask -> 6.2531, id -> USDCNY, Bid -> 6.2533, Date -> 4/28/2014, Time -> 6:15am)

From Here,

How can I bind a Map to scala properties,

class Currency(Rate:String, Ask:String, id:String, Bid:String, Date:String, Time:String)

Thanks in advance

BalaB
  • 3,687
  • 9
  • 36
  • 58
  • 1
    Please show more detail on what you are attempting and what you have already tried. What JSON library are you using (or are you just processing this data as a String)? What kind of Scala object are you trying to extract? – DNA Apr 28 '14 at 10:12
  • Hope now my question makes some sense... – BalaB Apr 29 '14 at 08:42
  • @BalaB I've updated my answer based on the additional details you provided. – godfatherofpolka Apr 29 '14 at 11:35

1 Answers1

3

There are many different ways of doing this, here is a straightforward one using Argonaut. For more ways of handling JSON in Scala, see What JSON library to use in Scala? and How to parse JSON in Scala using standard Scala classes?

import argonaut._, Argonaut._

case class Rate(id : String, rate : Double, date : java.util.Date, ask : Double, bid : Double)
object Rate {    
  val dateFormat = new java.text.SimpleDateFormat("M/d/yyyy h:mma")

  implicit def RateDecodeJson : DecodeJson[Rate] =
    DecodeJson(cursor => {
      val c = cursor --\ "query" --\ "results" --\ "rate"
      for {
        /* you can also access other fields of the JSON here, e.g. 
         * lang <- (cursor --\ "query" --\ "lang").as[String].map(new java.util.Locale(_))
         */
        id <- (c --\ "id").as[String]
        rate <- (c --\ "Rate").as[String].map(_.toDouble)
        date <- (c --\ "Date").as[String]
        time <- (c --\ "Time").as[String]
        ask <- (c --\ "Ask").as[String].map(_.toDouble)
        bid <- (c --\ "Bid").as[String].map(_.toDouble)
      } yield Rate(id, rate, dateFormat.parse(date + " " + time), ask, bid)})
}

object ArgonautExample extends App{
  val json = """{
      "query":{
        "count":1,
        "created":"2014-04-28T07:33:09Z",
        "lang":"en-US",
        "results":{
          "rate":{
            "id":"USDCNY",
            "Rate":"6.2489",
            "Date":"4/28/2014",
            "Time":"3:30am",
            "Ask":"6.2494",
            "Bid":"6.2484"
          }
        }
      }
    }"""

  val rate = Parse.decodeOption[Rate](json).get
  println(rate)
}

Note: You probably want to handle date and time in a slightly more sophisticated manner, e.g., using locales, etc.

If you don't mind the fields of Rate being all of type String (which is what the JSON delivers them as), you can also use the simpler version

case class Rate(id : String, rate : String, date : String, time : String, ask : String, bid : String)
object Rate {
  implicit def RateCodecJson : CodecJson[Rate] =
    casecodec6(Rate.apply, Rate.unapply)("id", "Rate", "Date", "Time", "Ask", "Bid")
}

and then first parse the whole JSON

val parsedJson = Parse.parseOption(json).get

and access and decode the relevant part

val rateJson = (parsedJson -|| List("query", "results", "rate")).get
val rate = rateJson.as[Rate].value.get
Community
  • 1
  • 1
godfatherofpolka
  • 1,645
  • 1
  • 11
  • 24