我正在使用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之间转换
发布评论