Skip to main content

Circe

Differ instances for Circe Json and JsonObject can be found in

"com.github.jatcwang" %% "difflicious-circe" % "v0.6.0" % Test

Import difflicious.circe.* to bring difflicious circe support into scope:

import difflicious.circe.{*, given}

import difflicious.*
import difflicious.implicits.*
import io.circe.{Json, JsonObject}

Differ for io.circe.Json and io.circe.JsonObject

Use Differ[Json] to diff io.circe.Json values

  • JSON objects are diffed like Map
  • JSON arrays are diffed like Seq

Differ[Json] example

val nestedJsonDiff = Differ[Json].diff(
json"""
{
"name": "Alice",
"age": 30,
"tags": ["admin", "active"]
}
""",
json"""
{
"name": "Alice",
"age": 31,
"tags": ["admin", "inactive"]
}
""",
)
JsonObject(
  "name" -> "Alice",
  "age" -> 30 -> 31,
  "tags" -> JArray(
      "admin",
      "active" -> "inactive"
    )
)

Differ[JsonObject] example

val jsonObjectDiff = Differ[JsonObject].diff(
JsonObject("name" -> Json.fromString("Alice")),
JsonObject("name" -> Json.fromString("Bob")),
)
JsonObject(
  "name" -> "Alice" -> "Bob"
)

Configuring JSON differs

Circe's internal JSON AST are public, so difflicious provides marker types for path configuration: JNull, JBoolean, JNumber, JString, and JArray.

val ignoreJsonNumbers: Differ[Json] =
Differ[Json].ignoreAt(_.subType[JNumber])

val ignoreNumbersInsideJsonArrays: Differ[Json] =
Differ[Json].ignoreAt(_.subType[JArray].each.subType[JNumber])

val ignoreNumbersInsideJsonObjects: Differ[Json] =
Differ[Json].ignoreAt(_.subType[JsonObject].each.subType[JNumber])
val ignoredJsonObjectNumberDiff = ignoreNumbersInsideJsonObjects.diff(
json"""
{"age": 30, "name": "Alice"}
""",
json"""
{"age": 31, "name": "Bob"}
""",
)
JsonObject(
  "age" -> [IGNORED],
  "name" -> "Alice" -> "Bob"
)

A Differ[JsonObject] can also be configured using .each

Differ[JsonObject].ignoreAt(_.each.subType[JNumber])