加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

Scala到JSON在Play Framework 2.1中

发布时间:2020-12-16 09:41:31 所属栏目:安全 来源:网络整理
导读:我正在尝试将Scala转换为2.1RC Play Framework中的JSON。 我可以执行以下操作并获取JSON: import play.api.libs.json._val a1=Map("val1"-"a","val2"-"b")Json.toJSon(a1) 因为a1只是Map [String,String]可以正常工作。 但是如果我有更复杂的地方,我有Map
我正在尝试将Scala转换为2.1RC Play Framework中的JSON。

我可以执行以下操作并获取JSON:

import play.api.libs.json._

val a1=Map("val1"->"a","val2"->"b")
Json.toJSon(a1)

因为a1只是Map [String,String]可以正常工作。

但是如果我有更复杂的地方,我有Map [String,Object]的地方,那就不行了:

val a = Map("val1" -> "xxx","val2"-> List("a","b","c"))
Json.toJSon(a1)
>>> error: No Json deserializer found for type scala.collection.immutable.Map[String,Object]

我发现我可以做如下的事情:

val a2 = Map("val1" -> Json.toJson("a"),"val2" -> Json.toJson(List("a","c")))
Json.toJson(a2)

这有用

但是我怎么能这样做呢?我以为我可以做如下的事情:

a.map{ case(k,v)=> (k,Json.toJson(v) )}
>>> error: No Json deserializer found for type Object

但是我仍然收到一个不能反序列化的错误

附加信息:

Json.toJson可以将Map [String,String]转换为JsValue:

scala> val b = Map( "1" -> "A","2" -> "B","3" -> "C","4" -> "D" )
b: scala.collection.immutable.Map[String,String] = Map(1 -> A,2 -> B,3 -> C,4 -> D)

scala> Json.toJson(b)
res31: play.api.libs.json.JsValue = {"1":"A","2":"B","3":"C","4":"D"}

但是,它尝试转换Map [String,Object]时失败:

scala> a
res34: scala.collection.immutable.Map[String,Object] = Map(val1 -> xxx,val2 -> List(a,b,c))

scala> Json.toJson(a)
<console>:12: error: No Json deserializer found for type scala.collection.immutable.Map[String,Object]. Try to implement an implicit Writes or Format for this type.
          Json.toJson(a)

使用此Play Framework页面上的“提示”将Scala转换为Json,我发现以下(http://www.playframework.org/documentation/2.0.1/ScalaJson):

如果不是Map [String,Object],则有一个Map [String,JsValue],那么Json.toJson()将会工作:

scala> val c = Map("aa" -> Json.toJson("xxxx"),"bb" -> Json.toJson( List("11","22","33") ) )
c: scala.collection.immutable.Map[String,play.api.libs.json.JsValue] = Map(aa -> "xxxx",bb -> ["11","33"])

scala> Json.toJson(c)
res36: play.api.libs.json.JsValue = {"aa":"xxxx","bb":["11","33"]}

所以,我想要的是,给定一个Map [String,Object],我知道Object值最初是String或List [String],如何将Json.toJson()函数应用于所有映射中的值并获取Map [String,JsValue]。

我还发现,我可以过滤出纯粹是字符串的那些值,以及List(String)类型的值。

scala> val a1 = a.filter({case(k,v) => v.isInstanceOf[String]})
a1: scala.collection.immutable.Map[String,Object] = Map(val1 -> xxx)

scala> val a2 = a.filter({case(k,v) => v.isInstanceOf[List[String]]})
<console>:11: warning: non-variable type argument String in type List[String] is unchecked since it is eliminated by erasure
   val a2 = a.filter({case(k,v) => v.isInstanceOf[List[String]]})
                                                 ^
a2: scala.collection.immutable.Map[String,Object] = Map(val2 -> List(a,c))

List [String]过滤提供了一个警告,但似乎给出了我想要的答案。如果这两个过滤器可以被应用,然后Json.toJson()用于结果的值,结果结合起来,也许会有效?

但是,过滤的结果仍然是Map [String,Object]类型,导致问题:

scala> Json.toJson(a1)
<console>:13: error: No Json deserializer found for type scala.collection.immutable.Map[String,Object]. Try to implement an implicit Writes or Format for this type.
          Json.toJson(a1)

解决方法

播放2.1 JSON API不提供类型映射[String,Ojbect]的序列化程序。

为特定类型定义案例类和格式,而不是Map [String,Object]:

// { "val1" : "xxx","val2" : ["a","c"] }
case class Hoge(val1: String,val2: List[String])

implicit val hogeFormat = Json.format[Hoge]

如果你不想创建case类。
以下代码为Map [String,Object]提供了JSON序列化器/解串器:

implicit val objectMapFormat = new Format[Map[String,Object]] {

  def writes(map: Map[String,Object]): JsValue =
    Json.obj(
      "val1" -> map("val1").asInstanceOf[String],"val2" -> map("val2").asInstanceOf[List[String]]
    )

  def reads(jv: JsValue): JsResult[Map[String,Object]] =
    JsSuccess(Map("val1" -> (jv  "val1").as[String],"val2" -> (jv  "val2").as[List[String]]))
}

更动态

import play.api.libs.json._
import play.api.libs.json.Reads._
import play.api.libs.json.Json.JsValueWrapper

implicit val objectMapFormat = new Format[Map[String,Object]): JsValue = 
    Json.obj(map.map{case (s,o) =>
      val ret:(String,JsValueWrapper) = o match {
        case _:String => s -> JsString(o.asInstanceOf[String])
        case _ => s -> JsArray(o.asInstanceOf[List[String]].map(JsString(_)))
      }
      ret
    }.toSeq:_*)


  def reads(jv: JsValue): JsResult[Map[String,Object]] =
    JsSuccess(jv.as[Map[String,JsValue]].map{case (k,v) =>
      k -> (v match {
        case s:JsString => s.as[String]
        case l => l.as[List[String]]
      })
    })
}

示例代码:

val jv = Json.toJson(Map("val1" -> "xxx","val2" -> List("a","c"),"val3" -> "sss","val4" -> List("d","e","f")))
  println(jv)
  val jr = Json.fromJson[Map[String,Object]](jv)
  println(jr.get)

输出:

> {"val1":"xxx","val2":["a","c"],"val3":"sss","val4":["d","f"]}
> Map(val1 -> xxx,c),val3 -> sss,val4 -> List(d,e,f))

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读