Scala 映射到 JSON 递归

Scala Map to JSON Recursive

大家好,我正在编写一个 Scala 函数,它最终会 return 两个地图的增量我正在递归执行此操作,因为我不知道传入的地图会是什么样子。地图是转换后的 JSON 个对象。目前我正在编写一个函数,它通过地图解析地图和 returns 同一张地图,它最终将接受两个地图和 return 增量。当我到达 array/list 时遇到问题,不知道如何处理它们。任何指针将不胜感激。

EDIT: Okay, I got this recursive algorithm to work. I was returning inside the for loop, breaking the loop, duh.

这是我现在遇到的问题:

JSON 在:

{"name":"Watership Down","location":{"lat":51.235685,"long":-1.309197},"residents":[{"name":"Fiver","age":4,"role":""},{"name":"Bigwig","age":6,"role":"Owsla"}]}

Json输出:

{"location":{"lat":51.235685,"long":-1.309197},"name":"Watership Down","residents":[{"role":"","age":4,"name":"Fiver"},{"role":"Owsla","age":6,"name":"Bigwig"}]}

EDIT: It all works. I was using scala.collection.mutable in CompareMaps, cahnged it to immutable and it doesn't mess with the order. ( Found this issue here: Whosebug post) It works now!

代码:

import play.api.libs.json.{JsNull,Json,JsString,JsValue}
import play.api.libs.json._
import com.fasterxml.jackson.databind.{DeserializationFeature, ObjectMapper}
import org.json4s._
import org.json4s.jackson.JsonMethods._
import org.json4s.jackson.Serialization
import scala.util.matching.Regex
import scala.collection.mutable.ListBuffer


object JsonCompare {
def main(args: Array[String]): Unit = {

  val jsonT: JsValue = JsObject(Seq(
            "name" -> JsString("andrew"),
            "race" -> JsString("white"),
            "characteristics" -> JsObject(Seq(
                "body"-> JsString("avg"),
                "height" -> JsString("tall"),
                "head"-> JsObject(Seq(
                  "eyes" -> JsString("blue"),
                  "hair" -> JsString("brown")
                  ))
                ))
    ))

  val jsonZ: JsValue = JsObject(Seq(
    "name" -> JsString("Watership Down"),
    "location" -> JsObject(Seq("lat" -> JsNumber(51.235685), "long" -> JsNumber(-1.309197))),
    "residents" -> JsArray(Seq(
      JsObject(Seq(
        "name" -> JsString("Fiver"),
        "age" -> JsNumber(4),
        "role" -> JsString("")
      )),
      JsObject(Seq(
        "name" -> JsString("Bigwig"),
        "age" -> JsNumber(6),
        "role" -> JsString("Owsla")
      ))
    ))
  )) 

  var jsonTMap:Map[String, Any] = Map()
  val jsonTString: String = Json.stringify(jsonT)
  jsonTMap = jsonStrToMap(jsonTString) 

  implicit val formats = org.json4s.DefaultFormats

  val jsonA: JsValue = Json.obj(
      "name" -> "Bob",
      "location" -> "Irvine",
      "resident" -> "No",
      "nick-name" -> "Bigwig",
      "age" -> "6",
      "role" -> "Owsla",
      "car" -> "BMW",
      "multiple-residents" -> JsArray(Seq(
        JsObject(Seq(
          "name" -> JsString("Fiver"),
          "age" -> JsNumber(4),
          "role" -> JsObject(Seq(
                      "position" -> JsString("Fiver"),
                      "" -> JsNumber(4),
                      "role" -> JsString("janitor")
                    ))
        ))
      ))
  )

  val jsonB: JsValue = Json.obj(
      "name" -> "Anrew",
      "location" -> JsString("Elmwood Park"),
      "resident" -> "Yes",
      "nick-name" -> "Drew",
      "age" -> JsNumber(4384),
      "role" -> "Programmer",
      "house" -> JsBoolean(true),
      "multiple-residents" -> JsArray(Seq(
        JsObject(Seq(
          "name" -> JsString("James"),
          "age" -> JsNumber(8),
          //"role" -> JsObject(Seq(
                      "position" -> JsString("Sr. Programmer"),
                      "" -> JsNumber(10),
                      "role" -> JsString("Serious")
                   // ))
        ))
      ))
  )
  //Original json object
  var jsonAMap:Map[String, Any] = Map()
  val jsonAString: String = Json.stringify(jsonA)
  jsonAMap = jsonStrToMap(jsonAString) 

  //Changed json object
  var jsonBMap:Map[String, Any] = Map()
  val jsonBString: String = Json.stringify(jsonB)
  jsonBMap = jsonStrToMap(jsonBString) 


  var jsonZMap:Map[String, Any] = Map()
  val jsonZString: String = Json.stringify(jsonZ)

  jsonZMap = jsonStrToMap(jsonZString) 
  println(Serialization.write(jsonZMap))
  println(Serialization.write(compareMaps(jsonZMap)))

  //println(jsonTMap)
  //println(compareMaps(jsonTMap))
  //println(Serialization.write(compareMaps(jsonTMap)))

  //println(compareMaps(jsonTMap))
  //println(Serialization.write(compareMaps(jsonTMap)))
}

//convert json to Map using json4s library
def jsonStrToMap(jsonStr: String): Map[String, Any] = {
  implicit val formats = org.json4s.DefaultFormats
  parse(jsonStr).extract[Map[String, Any]]
}

def compareMaps(mapA: Map[String, Any]): Map[String,Any] = {
  //deltaMap will store all the differences 
  var deltaMap = scala.collection.mutable.Map[String, Any]()

  var typeOf :String = "" 
  //for every value in the map, check if it's a map, if it is go into it and do the difference check.
  for((key,value) <- mapA){

    typeOf = value.getClass.getSimpleName

    if(typeOf.matches("Map[0-9]")){
      deltaMap += (key -> compareMaps(value.asInstanceOf[Map[String,Any]]))
    }else if(typeOf == "$colon$colon"){
      deltaMap += (key ->  parseList(value.asInstanceOf[List[Any]]))
    }else{
      deltaMap += (key -> value)
    }

  }//end of for((key,value) <- mapA

  implicit val formats = org.json4s.DefaultFormats

  return((scala.collection.immutable.Map() ++ deltaMap))
}//end of compareMaps

def parseList(values: List[Any]): List[Any] = {
  var deltaList = new ListBuffer[Any]()
  var typeOf :String = ""
  for(value <- values){
    typeOf = value.getClass.getSimpleName
    if(typeOf == "$colon$colon"){
      parseList(value.asInstanceOf[List[Any]])
    }else{
      deltaList += compareMaps(value.asInstanceOf[Map[String, Any]])
    }
  }
  return (deltaList.toList)
}//end of parseList

//end of class
}

已解决。请看上面。我希望这对将来的人有用。