The Scala Toolkit

How to access values inside JSON?

Language

Using Scala CLI, you can require the entire toolkit in a single line:

//> using toolkit latest

Alternatively, you can require just a specific version of UPickle:

//> using dep com.lihaoyi::upickle:3.1.0

In your build.sbt file, you can add the dependency on the Toolkit:

lazy val example = project.in(file("."))
  .settings(
    scalaVersion := "3.3.4",
    libraryDependencies += "org.scala-lang" %% "toolkit" % "0.1.7"
  )

Alternatively, you can require just a specific version of UPickle:

libraryDependencies += "com.lihaoyi" %% "upickle" % "3.1.0"

In your build.sc file, you can add the dependency to the upickle library:

object example extends ScalaModule {
  def scalaVersion = "3.3.4"
  def ivyDeps =
    Agg(
      ivy"org.scala-lang::toolkit:0.1.7"
    )
}

Alternatively, you can require just a specific version of UPickle:

ivy"com.lihaoyi::upickle:3.1.0"

Accessing values inside JSON

To parse a JSON string and access fields inside it, you can use uJson, which is part of uPickle.

The method ujson.read parses a JSON string into memory:

val jsonString = """{"name": "Peter", "age": 13, "pets": ["Toolkitty", "Scaniel"]}"""
val json: ujson.Value  = ujson.read(jsonString)
println(json("name").str)
// prints: Peter

To access the "name" field, we do json("name") and then call str to type it as a string.

To access the elements by index in a JSON array,

val pets: ujson.Value = json("pets")

val firstPet: String = pets(0).str
val secondPet: String = pets(1).str

println(s"The pets are $firstPet and $secondPet")
// prints: The pets are Toolkitty and Scaniel

You can traverse the JSON structure as deeply as you want, to extract any nested value. For instance, json("field1")(0)("field2").str is the string value of field2 in the first element of the array in field1.

JSON types

In the previous examples we used str to type a JSON value as a string. Similar methods exist for other types of values, namely:

  • num for numeric values, returning Double
  • bool for boolean values, returning Boolean
  • arr for arrays, returning a mutable Buffer[ujson.Value]
  • obj for objects, returning a mutable Map[String, ujson.Value]
import scala.collection.mutable

val jsonString = """{"name": "Peter", "age": 13, "pets": ["Toolkitty", "Scaniel"]}"""
val json = ujson.read(jsonString)

val person: mutable.Map[String, ujson.Value] = json.obj
val age: Double = person("age").num
val pets: mutable.Buffer[ujson.Value] = person("pets").arr

If a JSON value does not conform to the expected type, uJson throws a ujson.Value.InvalidData exception.

val name: Boolean = person("name").bool
// throws a ujson.Value.InvalidData: Expected ujson.Bool (data: "Peter")

Contributors to this page: