Working with JSON in Scala.js
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:
- uPickle
- Circe
- scalajs-dom (using JSON.stringify() and parse())
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.