Parsing JSON
circe includes a parsing module, which on the JVM is a wrapper around the Jawn JSON parser and for JavaScript uses the built-in JSON.parse
.
Parsing is not part of the circe-core
module, so you will need to include a dependency on the circe-parser
module in your build:
libraryDependencies += "io.circe" %% "circe-parser" % circeVersion
Parsing is done as follows.
import io.circe._, io.circe.parser._
val rawJson: String = """
{
"foo": "bar",
"baz": 123,
"list of stuff": [ 4, 5, 6 ]
}
"""
// rawJson: String = """
// {
// "foo": "bar",
// "baz": 123,
// "list of stuff": [ 4, 5, 6 ]
// }
// """
val parseResult = parse(rawJson)
// parseResult: Either[ParsingFailure, Json] = Right(
// value = JObject(
// value = object[foo -> "bar",baz -> 123,list of stuff -> [
// 4,
// 5,
// 6
// ]]
// )
// )
Because parsing might fail, the result is an Either
with an io.circe.Error
on the left side.
In the example above, the input was valid JSON, so the result was a Right
containing the
corresponding JSON representation.
Let's see what happens when you try to parse invalid JSON:
val badJson: String = "yolo"
// badJson: String = "yolo"
parse(badJson)
// res0: Either[ParsingFailure, Json] = Left(
// value = ParsingFailure(
// message = "expected json value got 'yolo' (line 1, column 1)",
// underlying = ParseException(
// msg = "expected json value got 'yolo' (line 1, column 1)",
// index = 0,
// line = 1,
// col = 1
// )
// )
// )
There are a number of ways to extract the parse result from the Either
. For example you could pattern
match on it:
parse(rawJson) match {
case Left(failure) => println("Invalid JSON :(")
case Right(json) => println("Yay, got some JSON!")
}
// Yay, got some JSON!
Or use getOrElse
(an extension method provided by Cats):
val json: Json = parse(rawJson).getOrElse(Json.Null)
// json: Json = JObject(
// value = object[foo -> "bar",baz -> 123,list of stuff -> [
// 4,
// 5,
// 6
// ]]
// )
Warnings and known issues
When using the Scala.js version of circe, numerical values like Long
may lose
precision when decoded. For example decode[Long]("767946224062369796")
will return Right(767946224062369792L)
. This is not a limitation of how
Scala.js represents scala.Long
s nor circe's decoders for numerical values but
due to JSON.parse
converting numerical values to JavaScript
numbers. If precision is required consider representing numerical values as
strings and convert them to their final value via the JSON AST.