Как уже было предложено @ dk14, вы можете использовать diffson librarry: https://github.com/gnieh/diffson - но структура JsonPatch
, которую она предоставляет, может быть не очень удобна для вашего случая использования, поэтому ее можно преобразовать в другой, чтобы получить результат в нужном формате. Пожалуйста, посмотрите пример кода ниже:
import diffson.jsonpatch.{Add, JsonPatch, Remove, Replace}
import diffson.jsonpointer.{Part, Pointer}
import io.circe.Json
// Model representing plain json diff at certain path, that can be rendered at more human readable format
case class JsonPathDiff(path: Pointer, left: Option[Json], right: Option[Json]) {
def readableString: String = {
val pathReadableString: String = {
def partToString(part: Part): String = part.fold(identity, _.toString)
path.parts.toList.map(partToString).mkString(".")
}
def jsonReadableValue(json: Option[Json]): String = json.map(_.toString()).getOrElse("")
val leftValue = jsonReadableValue(left)
val rightValue = jsonReadableValue(right)
s"$pathReadableString = $leftValue , $rightValue"
}
}
// Model representing overall difference between two JSON's
case class JsonDiff(diff: List[JsonPathDiff]) {
def readableString: String = diff.map(_.readableString).mkString("\n")
}
object JsonDiff {
def fromPatch(patch: JsonPatch[Json]): JsonDiff = {
val paths = patch.ops.collect {
case Add(path, value) => JsonPathDiff(path, None, Some(value))
case Remove(path, old) => JsonPathDiff(path, old, None)
case Replace(path, value, old) => JsonPathDiff(path, old, Some(value))
}
JsonDiff(paths)
}
}
def main(args: Array[String]): Unit = {
import diffson._
import diffson.circe._
import diffson.jsonpatch._
import diffson.jsonpatch.lcsdiff.remembering._
import diffson.lcs._
import io.circe._
import io.circe.parser._
val json1 =
s"""{
"name": "Henry",
"age" : 26,
"activities" : {
"school": "basketball club",
"after-school": "chess"
}
}"""
val json2 =
s"""{
"name": "David",
"age" : 23,
"activities" : {
"school": "baseball club",
"after-school": "programming"
}
}"""
implicit val lcs = new Patience[Json]
val patch: Either[ParsingFailure, JsonPatch[Json]] =
for {
json1 <- parse(json1)
json2 <- parse(json2)
} yield diff(json1, json2)
val jsonDiff = JsonDiff.fromPatch(patch.right.get) // Using `get` for sake of example, avoid in real production code
println(jsonDiff.readableString)
}
, который даст следующий результат:
activities.after-school = "chess" , "programming"
activities.school = "basketball club" , "baseball club"
age = 26 , 23
name = "Henry" , "David"
Надеюсь, это поможет!