在Scala中比较JSON的相等性

19

我该如何在Scala中比较两个JSON结构是否相同?

例如,如果我有:

{
  resultCount: 1,
  results: [
    {
      artistId: 331764459,
      collectionId: 780609005
    }
  ]
}

{
  results: [
    {
      collectionId: 780609005,
      artistId: 331764459
    }
  ],
  resultCount: 1
}

它们应被视为相等


1
你想让它们被视为不同的吗? - interlude
我希望它们被视为相等。 - Daniel Cukier
5个回答

17

如果JSON库编写正确,您应该能够简单地执行json1 == json2。 这对于使用spray-json的情况也是如此,但我期望每个JSON库都是一样的。

import spray.json._
import DefaultJsonProtocol._
Welcome to Scala version 2.10.4 (OpenJDK 64-Bit Server VM, Java 1.7.0_51).
Type in expressions to have them evaluated.
Type :help for more information.

scala> val json1 = """{ "a": 1, "b": [ { "c":2, "d":3 } ] }""".parseJson
json1: spray.json.JsValue = {"a":1,"b":[{"c":2,"d":3}]}

scala> val json2 = """{ "b": [ { "d":3, "c":2 } ], "a": 1 }""".parseJson
json2: spray.json.JsValue = {"b":[{"d":3,"c":2}],"a":1}

scala> json1 == json2
res1: Boolean = true

Spray-json使用一个不可变的Scala Map 来表示JSON对象在解析后的抽象语法树中,因此正是Map的相等语义让它能够工作。


2
您也可以使用scalatest-json
示例:

    it("should fail on slightly different json explaining why") {
      val input = """{"someField": "valid json"}""".stripMargin

      val expected = """{"someField": "different json"}""".stripMargin

      input should matchJson(expected)
    }


当两个JSON不匹配时,会显示一个漂亮的差异,这在处理大型JSON时非常有用。

1

可以确认使用==运算符的Jackson库也能正常工作:

val simpleJson =
  """
    |{"field1":"value1","field2":"value2"}
  """.stripMargin

val simpleJsonNode = objectMapper.readTree(simpleJson)

val simpleJsonNodeFromString = objectMapper.readTree(simpleJsonNode.toString)

assert(simpleJsonNode == simpleJsonNodeFromString)

0

spray-json 确实很不错,但是因为我已经在我的项目中依赖于 Gson 库,所以我使用了它。我在我的单元测试中使用它们,对于简单的 JSON 工作得很好。

import com.google.gson.{JsonParser}
import org.apache.flume.event.JSONEvent
import org.scalatest.FunSuite

class LogEnricherSpec extends FunSuite {
  test("compares json to json") {

    val parser = new JsonParser()

    assert(parser.parse("""
        {
          "eventType" : "TransferItems",
          "timeMillis" : "1234567890",
          "messageXml":{
            "TransferId" : 123456
          }
        } """.stripMargin)
      ==
      parser.parse("""
        {
          "timeMillis" : "1234567890",
          "eventType" : "TransferItems",
          "messageXml":{
            "TransferId" : 123456
          }
        }
      """.stripMargin))
}

-8
调用方法compare_2Json(str1,str2)将返回布尔值。请确保两个字符串参数都是json格式。 欢迎使用和测试。
      def compare_2Json(js1:String,js2:String): Boolean = {
        var js_str1 = js1
        var js_str2 = js2

        js_str1=js_str1.replaceAll(" ","")
        js_str2=js_str2.replaceAll(" ","")
        var issame = false
        val arrbuff1 = ArrayBuffer[String]()
        val arrbuff2 = ArrayBuffer[String]()
        if(js_str1.substring(0,1)=="{" && js_str2.substring(0,1)=="{" || js_str1.substring(0,1)=="["&&js_str2.substring(0,1)=="["){
          for(small_js1 <- split_JsonintoSmall(js_str1);small_js2 <- split_JsonintoSmall((js_str2))) {
            issame = compare_2Json(small_js1,small_js2)
            if(issame == true){
              js_str1 = js_str1.substring(0,js_str1.indexOf(small_js1))+js_str1.substring(js_str1.indexOf(small_js1)+small_js1.length)
              js_str2 = js_str2.substring(0,js_str2.indexOf(small_js2))+js_str2.substring(js_str2.indexOf(small_js2)+small_js2.length)
            }
          }
          js_str1 = js_str1.substring(1,js_str1.length-1)
          js_str2 = js_str2.substring(1,js_str2.length-1)

          for(str_js1 <- js_str1.split(","); str_js2 <- js_str2.split(",")){
            if(str_js1!="" && str_js2!="")
              if(str_js1 == str_js2){
                js_str1 = js_str1.substring(0,js_str1.indexOf(str_js1))+js_str1.substring(js_str1.indexOf(str_js1)+str_js1.length)
                js_str2 = js_str2.substring(0,js_str2.indexOf(str_js2))+js_str2.substring(js_str2.indexOf(str_js2)+str_js2.length)
              }
          }
          js_str1=js_str1.replace(",","")
          js_str2=js_str2.replace(",","")

          if(js_str1==""&&js_str2=="")return true
          else return false
        }
        else return false
      }

      def split_JsonintoSmall(js_str: String):ArrayBuffer[String]={
        val arrbuff = ArrayBuffer[String]()

        var json_str = js_str
        while(json_str.indexOf("{",1)>0 || json_str.indexOf("[",1)>0){
          if (json_str.indexOf("{", 1) < json_str.indexOf("[", 1) && json_str.indexOf("{",1)>0 || json_str.indexOf("{", 1) > json_str.indexOf("[", 1) && json_str.indexOf("[",1)<0 ) {
            val right = findrealm(1, json_str, '{', '}')
            arrbuff += json_str.substring(json_str.indexOf("{", 1), right + 1)
            json_str = json_str.substring(0,json_str.indexOf("{",1))+json_str.substring(right+1)
          }
          else {
            if(json_str.indexOf("[",1)>0) {
              val right = findrealm(1, json_str, '[', ']')
              arrbuff += json_str.substring(json_str.indexOf("[", 1), right + 1)
              json_str = json_str.substring(0, json_str.indexOf("[", 1)) + json_str.substring(right + 1)
            }
          }
        }
        arrbuff
      }

  def findrealm(begin_loc: Int, str: String, leftch: Char, rightch: Char): Int = {
    var left = str.indexOf(leftch, begin_loc)
    var right = str.indexOf(rightch, left)
    left = str.indexOf(leftch, left + 1)
    while (left < right && left > 0) {
      right = str.indexOf(rightch, right + 1)
      left = str.indexOf(leftch, left + 1)
    }
    right
  }

1
js_str1.replaceAll(" ", "") -- 这将从字符串值中删除空格,使得 "foo bar" 等于 "foobar",对吗? - Jonas Kölker

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接