0

I have two json string having different order of some of the items, so they are like equal, and I want to compare them for equality, but not sure how to achieve it.

JSON 1

{
"data": [
 {
  "configTemplateId": "44f11ed4-5b08-11ea-8e2d-0242ac132222",
  "params": {
    "keyOne": "valueOne",
    "keyTwo": "valueTwo"
  }
 },
 {
  "configTemplateId": "44f11ed4-5b08-11ea-8e2d-0242ac131111",
  "params": {
    "keyOne": "valueOne",
    "keyTwo": "valueTwo"
   }
 }
]}

JSON 2

{
"data": [
{
  "configTemplateId": "44f11ed4-5b08-11ea-8e2d-0242ac131111",
  "params": {
    "keyOne": "valueOne",
    "keyTwo": "valueTwo"
  }
},
{
  "configTemplateId": "44f11ed4-5b08-11ea-8e2d-0242ac132222",
  "params": {
    "keyOne": "valueOne",
    "keyTwo": "valueTwo"
  }
}
]}

I have tried using spray-json as mentioned in Compare json equality in Scala but that does not seem working.

thedevd
  • 683
  • 11
  • 26

1 Answers1

1

You have to implement some kind of deepEquals. The idea is the following:

import play.api.libs.json.{JsArray, JsObject, JsValue, Json}
def deepEquals(json1: JsValue, json2: JsValue): Boolean = {
def sortArray(json: JsValue): JsValue = json match {
  case JsArray(arr) => JsArray(arr.map(sortArray).sortBy(_.toString))
  case other => other
}

if (json1.getClass != json2.getClass) {
  false
} else {
  (json1, json2) match {
    case (j1: JsObject, j2: JsObject) =>
      val fields1 = j1.value
      val fields2 = j2.value
      (fields1.keySet ++ fields2.keySet).foldLeft(true) { (acc, key) =>
        val field1 = fields1.get(key)
        val field2 = fields2.get(key)
        acc && ((field1, field2) match {
          case (Some(v1), Some(v2)) => deepEquals(v1, v2)
          case _ => false
        })
      }
    case (j1: JsArray, j2: JsArray) =>
      sortArray(j1) == sortArray(j2)
    case (other1, other2) => other1 == other2
  }
}

}

I used json play library, but with spray the implementation won't be much different

Oleg Zinoviev
  • 549
  • 3
  • 14