DEV Community

Fulton Byrne
Fulton Byrne

Posted on

Easy JSON with Scala

Update: I've been notified the json4s has some fairly severe and public DoS issues.

I'll make another post exploring this basic case using some of the libraries recommended in the thread.


I had been searching for an easy way to work with JSON in Scala. Most libraries expect the user wants to create advanced encoding and decoding functionality; therefore making them a bit difficult to jump into.

Fortunately I found this StackOverflow post that showed how to represent JSON using basic Scala data types such as Map, List, and String:

For example, I have this Map value in Scala:

val m = Map(
    "name" -> "john doe", 
    "age" -> 18, 
    "hasChild" -> true, 
    "childs" -> List(
        Map("name" -> "dorothy", "age" -> 5, "hasChild" -> false),
        Map("name" -> "bill", "age" -> 8, "hasChild" -> false)
    )
)

I want to convert…

The really big takeaway is that json4s performs recursive JSON encoding/decoding with fundamental Scala types where most basic libraries will only encode/decode one level deep.

Getting started is fairly easy.

1. Follow the installation steps for json4s.

  • Add the following to your build.sbt file:

    // Change 3.6.7 to whatever the latest version is on Maven Central
    libraryDependencies += "org.json4s" %% "json4s-native" % "3.6.7"
    

2. Decode JSON

  import org.json4s._
  import org.json4s.native.JsonMethods._

  object DecodeJSON extends App {
    val jsonString =
      """
        |{
        |  "hello": "world",
        |  "data": {
        |   "number": 12,
        |   "lie": false
        |   }
        |}
        |""".stripMargin

    val decoded = parse(jsonString)
    println(decoded)
    // JObject(List((hello,JString(world)),(data,JObject(List((number,JInt(12)), (lie,JBool(false)))))))
  }
Enter fullscreen mode Exit fullscreen mode
  • Notice the output uses special wrapper classes to represent the JSON data types and structure. The full list is found here.

3. Encoding JSON

Decoding recursively from Maps and Lists is possible as shown in the Stackoverflow post, but json4s provides a domain specific language (DSL) for creating JSON.

import org.json4s.JsonDSL._
import org.json4s.native.JsonMethods._

object Hello extends App {

// ~ is part of the json4s scala DSL
// it means these fields belong on the same Object level.
// It corresponds directly to a JSON comma (,).

  val jsonScala = ("hello" -> "world") ~
    ("data" ->
      ("number" -> 12) ~
        ("lie" -> false)
      )
  println(compact(render(jsonScala)))
  // {"hello":"world","data":{"number":12,"lie":false}}
}
Enter fullscreen mode Exit fullscreen mode

Conclusion

There are many JSON libraries for Scala out there, but json4s excels for quick and dirty projects involving dynamic JSON and simple types. Also, I'm really new to Scala so if you have a library you enjoy for working with JSON please share!

Top comments (1)

Collapse
 
plokhotnyuk profile image
Andriy Plokhotnyuk

CAUTION: json4s is vulnerable under DoS/DoW attacks which exploit hash collision vulnerabilities of Scala's HashMap or parsing vulnerabilities of Java's BigInteger/BigDecimal values:
github.com/json4s/json4s/issues?ut...

Please consider to use more safe and efficient JSON parsers for Scala, like:
github.com/sirthias/borer
github.com/circe/circe
github.com/pathikrit/dijon
github.com/plokhotnyuk/jsoniter-scala