How to use Lift-JSON to parse JSON array data

If you ever need to parse JSON stock data from alphavantage.co using Scala, here’s a test class I just wrote that uses Lift-JSON.

The JSON data format

First, here’s the JSON I get back from them:

{
    "Meta Data": {
        "1. Information": "Batch Stock Market Quotes",
        "2. Notes": "IEX Real-Time Price provided for free by IEX (https://iextrading.com/developer/).",
        "3. Time Zone": "US/Eastern"
    },
    "Stock Quotes": [
        {
            "1. symbol": "MSFT",
            "2. price": "91.6000",
            "3. volume": "23511825",
            "4. timestamp": "2018-01-22 16:00:00"
        },
        {
            "1. symbol": "FB",
            "2. price": "186.4000",
            "3. volume": "20946922",
            "4. timestamp": "2018-01-22 16:41:06"
        },
        {
            "1. symbol": "AAPL",
            "2. price": "176.8900",
            "3. volume": "27027474",
            "4. timestamp": "2018-01-22 16:00:00"
        }
    ]
}

I get that array back when I access a URL like this:

  • https://www.alphavantage.co/query?function=BATCH_STOCK_QUOTES&symbols=MSFT,FB,AAPL&apikey=demo

Parsing the JSON

Next, here’s how I parse that JSON using Scala and Lift-JSON:

import net.liftweb.json.DefaultFormats
import net.liftweb.json._
import scala.collection.mutable.ArrayBuffer

object Test2 extends App {

    val json = parse(SampleData.data)
    implicit val formats = DefaultFormats

    val elements = (json \\ "Stock Quotes").children

    val stocks = ArrayBuffer[Stock]()
    // keys are: "1. symbol", "2. price", "3. volume", "4. timestamp"
    // i expect 3 stocks, so ...
    for (i <- 0 until 3) {
        val e = elements(0)(i)
        // Map(1. symbol -> MSFT, 2. price -> 91.6000, 3. volume -> 23511825, 4. timestamp -> 2018-01-22...)
        val values = e.values.asInstanceOf[Map[String,String]]   //coercion
//        for ((k,v) <- values) printf("key: %s, value: %s\n", k, v)
//        println("")
        stocks += Stock(values("1. symbol"), values("2. price"))
    }

    stocks.foreach(println)

    case class Stock(symbol: String, price: String)


}

The output

The output of that code looks like this:

Stock(MSFT,91.6000)
Stock(FB,186.4000)
Stock(AAPL,176.8900)

Discussion

The source code is ugly I write now because I just got it working, but I thought I’d share it here in case you need to parse some JSON data that’s in an array format like this. I’m more used to working with JSON that represents objects — see my other Scala/JSON examples — but this data is more of an “array of arrays” format, so this approach is different than my previous examples.

My build.sbt file

As a final note, my build.sbt file looks like this:

name := "StockQuotes2018"

version := "1.0"

scalaVersion := "2.12.4"

libraryDependencies ++= Seq(
    "net.liftweb" %% "lift-json" % "3.1.1"
)

scalacOptions += "-deprecation"