JSON
Prerequisites: Type classes
Scala has several excellent JSON libraries. All map JSON to case classes through type classes, usually derived automatically.
upickle (simple and fast)
// illustrative
//> using dep com.lihaoyi::upickle:4.1.0
import upickle.default.*
case class Address(city: String, country: String) derives ReadWriter
case class User(name: String, age: Int, tags: List[String], address: Option[Address])
derives ReadWriter
@main def json(): Unit =
val ada = User("Ada", 36, List("admin"), Some(Address("London", "UK")))
val text = write(ada)
println(text)
println(read[User](text) == ada)
val parsed = ujson.read("""{"name": "Linus", "langs": ["C", "Rust"]}""")
println(parsed("langs")(1).str)
{"name":"Ada","age":36,"tags":["admin"],"address":{"city":"London","country":"UK"}}
true
Rust
circe (Typelevel ecosystem)
// illustrative
//> using dep io.circe::circe-generic:0.14.12
//> using dep io.circe::circe-parser:0.14.12
import io.circe.*, io.circe.syntax.*, io.circe.parser.*
case class Order(id: Int, total: BigDecimal) derives Codec.AsObject
@main def circe(): Unit =
println(Order(1, 59.97).asJson.noSpaces)
println(decode[Order]("""{"id": 2, "total": "oops"}"""))
{"id":1,"total":59.97}
Left(DecodingFailure at .total: Got value '"oops"' with wrong type, expecting number)
Decoding returns an Either, so invalid JSON is an ordinary value to
handle — no exceptions. Check sample payloads with the
JSON Formatter or
JSON Validator.
Choosing
- upickle — minimal, fast, great for scripts and Scala CLI.
- circe — the standard with Cats Effect, http4s, and Tapir.
- zio-json — the ZIO ecosystem's choice.
- jsoniter-scala — the fastest, using compile-time macros.