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" % "0.14.10"

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.Longs 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.