簡體   English   中英

如何在 play.api.libs.json.JsValue 和 org.json4s.JValue 之間進行轉換

[英]How can I convert between play.api.libs.json.JsValue and org.json4s.JValue

我正在使用 Play Framework 來構建 API,但需要使用僅使用 Json4s 的庫來執行一些驗證和轉換操作。

到目前為止,我唯一能夠開始工作的是轉換為字符串並使用目標庫進行解析:

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))

但這顯然是低效的,並且會產生丑陋的代碼。 有更好的方法嗎?

模式匹配和轉換

編寫從一種到另一種的隱式轉換。

模式匹配和轉換

  1. JsString 到 JString

  2. JsNull 到 JNull

  3. JsNumber 到 JNumber

  4. JsArray 到 JArray ...等等

使用 Intellij 的 ALT + ENTER 功能(如果您正在使用它)自動獲取所有案例對象和案例類以進行模式匹配(無需手動檢查源代碼)。

JsArray 和 JsObject 轉換為對應的 JArray 和 JObject 的情況下遞歸轉換。

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)
  }
}

當您想將一個轉換為另一個時,只需導入轉換對象

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)))))))

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM