如何在Scala中的play.api.libs.json.JsValue和or.json4s.JValue之间转换 [英] How can I convert between play.api.libs.json.JsValue and or.json4s.JValue in Scala

查看:116
本文介绍了如何在Scala中的play.api.libs.json.JsValue和or.json4s.JValue之间转换的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用Play Framework构建API,但是需要使用仅讲Json4s的库执行一些验证和转换操作.

I'm using Play Framework to build an API, but need to perform some validation and transformation operations with a library that only speaks Json4s.

到目前为止,我唯一能够开始工作的就是将其转换为字符串并使用目标库进行解析:

So far, the only thing I've been able to get to work is converting to a string and parsing with the target library:

import org.json4s._
import org.json4s.jackson.JsonMethods._    
import play.api.libs.json._

val playJson: JsValue = Json.parse(compact(render(json4sJson)))
val json4sJson: JValue = parse(Json.stringify(playJson))

但这显然效率低下,并且代码很丑陋.有更好的方法吗?

But that's obviously inefficient and makes for ugly code. Is there a better way?

推荐答案

模式匹配和转换

将隐式转换从一种转换成另一种.

Pattern match and convert

Write implicit conversions from one to other.

模式匹配并转换

1)JsString到JString

1) JsString to JString

2)从JsNull到JNull

2) JsNull to JNull

3)JsNumber到JNumber

3) JsNumber to JNumber

4)从JsArray到JArray ...等等

4) JsArray to JArray ... so on

使用Intellij的ALT + ENTER功能(如果正在使用它)自动获取所有案例对象和案例类以进行模式匹配(无需手动检查源代码).

在将JsArray和JsObject转换的情况下,将其递归转换为JArray和JObject.

Recursively convert in case of JsArray and JsObject conversion into JArray and JObject correspondingly.

import play.api.libs.{ json => pjson }
import org.{ json4s => j4s }

object Conversions {

  implicit def toJson4s(json: play.api.libs.json.JsValue):org.json4s.JValue = json match {
    case pjson.JsString(str) => j4s.JString(str)
    case pjson.JsNull => j4s.JNull
    case pjson.JsBoolean(value) => j4s.JBool(value)
    case pjson.JsNumber(value) => j4s.JDecimal(value)
    case pjson.JsArray(items) => j4s.JArray(items.map(toJson4s(_)).toList)
    case pjson.JsObject(items) => j4s.JObject(items.map { case (k, v) => k -> toJson4s(v)}.toList)
  }

  implicit def toPlayJson(json: org.json4s.JValue): play.api.libs.json.JsValue = json match {
    case j4s.JString(str) => pjson.JsString(str)
    case j4s.JNothing => pjson.JsNull
    case j4s.JNull => pjson.JsNull
    case j4s.JDecimal(value) => pjson.JsNumber(value)
    case j4s.JDouble(value) => pjson.JsNumber(value)
    case j4s.JInt(value) => pjson.JsNumber(BigDecimal(value))
    case j4s.JLong(value) => pjson.JsNumber(BigDecimal(value))
    case j4s.JBool(value) => pjson.JsBoolean(value)
    case j4s.JSet(fields) => pjson.JsArray(fields.toList.map(toPlayJson(_)))
    case j4s.JArray(fields) => pjson.JsArray(fields.map(toPlayJson(_)))
    case j4s.JObject(fields) => pjson.JsObject(fields.map { case (k, v) => k -> toPlayJson(v)}.toMap)
  }

}

无论何时要相互转换,只要导入转换对象

When ever you want to convert one to other, then Just import conversions object

import Conversions._

Scala REPL

scala> object Conversions {
     |
     |   implicit def toJson4s(json: play.api.libs.json.JsValue):org.json4s.JValue = json match {
     |     case pjson.JsString(str) => j4s.JString(str)
     |     case pjson.JsNull => j4s.JNull
     |     case pjson.JsBoolean(value) => j4s.JBool(value)
     |     case pjson.JsNumber(value) => j4s.JDecimal(value)
     |     case pjson.JsArray(items) => j4s.JArray(items.map(toJson4s(_)).toList)
     |     case pjson.JsObject(items) => j4s.JObject(items.map { case (k, v) => k -> toJson4s(v)}.toList)
     |   }
     |
     |   implicit def toPlayJson(json: org.json4s.JValue): play.api.libs.json.JsValue = json match {
     |     case j4s.JString(str) => pjson.JsString(str)
     |     case j4s.JNothing => pjson.JsNull
     |     case j4s.JNull => pjson.JsNull
     |     case j4s.JDecimal(value) => pjson.JsNumber(value)
     |     case j4s.JDouble(value) => pjson.JsNumber(value)
     |     case j4s.JInt(value) => pjson.JsNumber(BigDecimal(value))
     |     case j4s.JLong(value) => pjson.JsNumber(BigDecimal(value))
     |     case j4s.JBool(value) => pjson.JsBoolean(value)
     |     case j4s.JArray(fields) => pjson.JsArray(fields.map(toPlayJson(_)))
     |     case j4s.JObject(fields) => pjson.JsObject(fields.map { case (k, v) => k -> toPlayJson(v)}.toMap)
     |   }
     |
     | }
warning: there were two feature warnings; re-run with -feature for details
defined object Conversions

scala> import Conversions._
import Conversions._

scala> val json = pjson.Json.parse("""{"name": "pamu", "age": 1}""")
json: play.api.libs.json.JsValue = {"name":"pamu","age":1}

scala> toJson4s(json)
res0: org.json4s.JValue = JObject(List((name,JString(pamu)), (age,JDecimal(1))))

更多嵌套的Json

scala> val payload = pjson.Json.parse("""
     | {
     |   "firstName": "John",
     |   "lastName": "Smith",
     |   "isAlive": true,
     |   "age": 25,
     |   "address": {
     |     "streetAddress": "21 2nd Street",
     |     "city": "New York",
     |     "state": "NY",
     |     "postalCode": "10021-3100"
     |   },
     |   "phoneNumbers": [
     |     {
     |       "type": "home",
     |       "number": "212 555-1234"
     |     },
     |     {
     |       "type": "office",
     |       "number": "646 555-4567"
     |     },
     |     {
     |       "type": "mobile",
     |       "number": "123 456-7890"
     |     }
     |   ],
     |   "children": [],
     |   "spouse": null
     | }
     | """)
payload: play.api.libs.json.JsValue = {"firstName":"John","lastName":"Smith","isAlive":true,"age":25,"address":{"streetAddress":"21 2nd Street","city":"New York","state":"NY","postalCode":"10021-3100"},"phoneNumbers":[{"type":"home","number":"212 555-1234"},{"type":"office","number":"646 555-4567"},{"type":"mobile","number":"123 456-7890"}],"children":[],"spouse":null}

scala> toJson4s(payload)
res1: org.json4s.JValue = JObject(List((children,JArray(List())), (isAlive,JBool(true)), (spouse,JNull), (phoneNumbers,JArray(List(JObject(List((type,JString(home)), (number,JString(212 555-1234)))), JObject(List((type,JString(office)), (number,JString(646 555-4567)))), JObject(List((type,JString(mobile)), (number,JString(123 456-7890))))))), (age,JDecimal(25)), (lastName,JString(Smith)), (firstName,JString(John)), (address,JObject(List((streetAddress,JString(21 2nd Street)), (city,JString(New York)), (state,JString(NY)), (postalCode,JString(10021-3100)))))))

这篇关于如何在Scala中的play.api.libs.json.JsValue和or.json4s.JValue之间转换的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆