Introduction

Working with JSON is almost inevitable regardless of the environment. In this post, we will go through different ways of serializing/deserializing (or encoding/decoding as some may call it) objects from/to JSON in Scala.js. As of the date this post is written, there are three main tools that convert objects to/from JSON:

We will use the following object for all the examples for uPickle and Circe:

case class Car(id_disqus: String, brand: String, model: String) {}

using scalajs-dom requires a slight modification to the object as only js.Object is allowed

 class Car extends js.Object {
  var id_disqus: String = _
  var brand: String = _
  var model: String = _
}

Serializing

  • uPickle:

Using uPickle, it is enough to create an object that configures the types to be read/written :

import upickle.default.{ReadWriter => RW, macroRW}

object Car{
  implicit def rw: RW[Car] = macroRW
}

and then:

  val mercedes = new Car("1", "Mercedes", "2015")
    
    val mercedesJSON = write[Car](mercedes)

     println(mercedesJSON)
     //result: {"id":"1","brand":"Mercedes","model":"2015"}
     
  • Circe:

Circe requires the configuration of encoders/decoders:

import io.circe.{Decoder, Encoder}
import io.circe.generic.semiauto._

object Expense {
  implicit val carDecoder: Decoder[Car] = deriveDecoder
  implicit val carEncoder: Encoder[Car] = deriveEncoder
}

and then:

   import io.circe.syntax._
    val mercedes = new Car("1", "Mercedes", "2015")

    val mercedesJSON = mercedes.asJson

    println(mercedes.asJson)
     
     //result is indented by default 🙂 for making the output oneline : .asJson.noSpaces
     /*  {
      "id": "1",
      "brand": "Mercedes",
      "model": "2015"
      }
      */
  • scalajs-dom:

using scalajs-dom requires the addition of scalacOptions += "-P:scalajs:sjsDefinedByDefault" to the build file, since @ScalaJSDefined is meant to be deprecated.

and then :

    val mercedes = new Car()
    mercedes.id = "10"
    mercedes.model = "1980"
    mercedes.brand = "Mercedes"
    println(JSON.stringify(mercedes))
    //result: {"id":"10","brand":"Mercedes","model":"1980"}

Deserializing

  • uPickle:
    val mercedesJSON = """{"id":"10","brand":"Mercedes","model":"1980"}"""
    val mercedes = read[Car](mercedesJSON)
    println(mercedes.id)
    // 10
    println(mercedes.model)
    //  1980
    println(mercedes.brand)
    // Mercedes
  • Circe:
     val mercedesJSON = """{"id":"10","brand":"Mercedes","model":"1980"}"""
    val mercedes = decode[Car](mercedesJSON).toTry.get
    println(mercedes.id)
    // 10
    println(mercedes.model)
    //  1980
    println(mercedes.brand)
    // Mercedes
  • scalajs-dom:
    val mercedesJSON = """{"id":"10","brand":"Mercedes","model":"1980"}"""
    val mercedes = JSON.parse(mercedesJSON).asInstanceOf[Car]
    println(mercedes.id)
    // 10
    println(mercedes.model)
    //  1980
    println(mercedes.brand)
    // Mercedes

Wrap up

We have walked through different libraries that allow serializing/deserializing JSON in Scala.Js. All the methods work in pretty much the same way, so there is no preferred way. The choice is left to the developer.