Scala Play Framework JSON JsNull 使用 json4s

Scala Play Framework JSON JsNull using json4s

我是 Scala 的新手。如何处理代码中的 JsNull 值?

我正在使用 json4s 将 JSON 转换为地图。 我应该以某种方式将 JsNull 转换为 Option 吗?

示例:

播放 JSON : 创建 json

val jsonA: JsValue = Json.obj(
      "name" -> "Bob",
      "location" -> "Irvine",
      "resident" -> "No",
      "nick-name" -> "Bigwig",
      "age" -> "6",
      "role" -> JsNull,
      "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")
                    ))
        ))
      ))
)

json4s : 解析 json

var jsonAMap:Map[String, Any] = Map()
  val jsonAString: String = Json.stringify(jsonA)
  jsonAMap = jsonStrToMap(jsonAString) 

在使用 json4s 将 JsValue 转换为 Map 后,它看起来像这样:

Map(name -> Bob, location -> Irvine, role -> null, resident -> No, car -> BMW, multiple-residents -> List(Map(name -> Fiver, age -> 4, role -> Map(position -> Fiver,  -> 4, role -> janitor))), age -> 6, nick-name -> Bigwig)

当我创建一个 List 值时,我最终在列表中得到一个 null 值。一旦我对列表的所有值进行模式匹配,我最终会尝试模式匹配一​​个 null 这是不可能的(我确定我不应该对我的所有情况都使用遗嘱卡,但是我正在学习):

for(i <- 0 to beforeValsList.length - 1){
  beforeValsList(i) match { 
    case _ : Map[_,_] => 
      compareJson(
        beforeValsList(i).asInstanceOf[Map[String,Any]], 
        afterValsList(i).asInstanceOf[Map[String,Any]], 
        rdeltaBefore, rdeltaAfter, sameKeyList(i).toString()
      )
    case _ if (beforeValsList(i) != afterValsList(i)) => 
      // if i'm from a recursion, build a new map and add me 
      // to the deltas as a key->value pair
      rdeltaBefore += sameKeyList(i).toString -> beforeValsList(i)
      rdeltaAfter += sameKeyList(i).toString -> afterValsList(i)
    case _ => 
      println("catch all: " + beforeValsList(i).toString 
        + " " + afterValsList(i).toString)
  } 
}

json4s 将 JsNull 转换为 null。我应该做空检查吗:

if(!beforeValsList(i) == null){
      beforeValsList(i) match{...}
}

或者当我将 Map 中的值放入 List 时,是否有办法将 null 更改为 Option

我不确定最佳实践是什么以及为什么 jsno4s 将 JsNull 更改为 null 而不是 Option,以及这是否可行。

干杯。

我仍然不确定你想如何处理 JsNullnull(或者 None,如果你使用 Option),但你可以得到可以简化Map[String, Any]前后的区别:

type JsonMap = Map[String, Any]

def getMapDiffs(mapBefore: JsonMap, mapAfter: JsonMap) : (JsonMap, JsonMap) = {
  val sameKeys = mapBefore.keySet intersect mapAfter.keySet
  val startAcc = (Map.empty[String, Any], Map.empty[String, Any])
  sameKeys.foldLeft(startAcc){ case (acc @ (deltaBefore, deltaAfter), key) =>
    (mapBefore(key), mapAfter(key)) match {
      // two maps -> add map diff recursively to before diff and after diff
      case (beforeMap: Map[_, _], afterMap: Map[_, _]) =>
        val (deltaB, deltaA) = 
          getMapDiffs(beforeMap.asInstanceOf[JsonMap], afterMap.asInstanceOf[JsonMap])
        (deltaBefore + (key -> deltaB), deltaAfter + (key -> deltaA))
      // values before and after are different
      // add values to before diff and after diff
      case (beforeValue, afterValue) if beforeValue != afterValue =>
        (deltaBefore + (key -> beforeValue), deltaAfter + (key -> afterValue))
      // keep existing diff  
      case _ => acc
    }  
  }
}

可用作:

val (mapBefore, mapAfter) = (
  Map("a" -> "alpha", "b" -> "beta", "c" -> "gamma", "d" -> Map("e" -> "epsilon")),
  Map("a" -> "alpha", "b" -> List("beta"), "c" -> null, "d" -> Map("e" -> 3))
)

val (deltaBefore, deltaAfter) = getMapDiffs(mapBefore, mapAfter)
// deltaBefore: JsonMap = Map(b -> beta, c -> gamma, d -> Map(e -> epsilon))
// deltaAfter: JsonMap = Map(b -> List(beta), c -> null, d -> Map(e -> 3))

deltaBefore.toList
// List[(String, Any)] = List((b,beta), (c,gamma), (d,Map(e -> epsilon)))