如何在提取之前展平JValue?

时间:2014-01-08 21:29:28

标签: json4s

例如我的json数据就像:

[{
  "name": "Foo",
  "verified": {"email": true, "mobile": false}
}, {
  "name": "Bar",
  "verified": {"email": false, "mobile": false}
}]

使用json4s我可以获取一个JArray,在提取到User(case类)列表之前我想操作JArray - 我想要展平verified字段,这样用户会是这样的:

case class (name: String, emailVerified: Boolean, mobileVerified: Boolean)

我该怎么做?

1 个答案:

答案 0 :(得分:2)

您可以像这样转换现有的AST:

import org.json4s._
import org.json4s.jackson.JsonMethods._
import org.json4s.JsonDSL._

object test extends App {

  val json = """[{
             |  "name": "Foo",
             |  "verified": {"email": true, "mobile": false}
             |}, {
             |  "name": "Bar",
             |  "verified": {"email": false, "mobile": false}
             |}]""".stripMargin

  def t(js: JValue): JValue = for {
    JString(name) <- js \ "name"
    JBool(ver1) <- js \ "verified" \ "email"
    JBool(ver2) <- js \ "verified" \ "mobile"
  } yield ("name" -> name) ~ ("emailVerified" -> ver1) ~ ("mobileVerified" -> ver2)

  for {
    JArray(xs) <- parse(json)
  } yield JArray(xs map t)

}

另一种选择是为它编写自定义序列化程序:

import org.json4s._
import org.json4s.jackson.JsonMethods._
import org.json4s.JsonDSL._

object userTest extends App {

  val json = """{
               |  "name": "Bar",
               |  "verified": {"email": false, "mobile": false}
               |}""".stripMargin

  case class UserFoo(name: String, emailVerified: Boolean, mobileVerified: Boolean)

  class UserFooSerializer extends CustomSerializer[UserFoo](formats => ( {
    case js: JValue =>
      val u = for {
        JString(name) <- js \ "name"
        JBool(userVerified) <- js \ "verified" \ "email"
        JBool(mobileVerified) <- js \ "verified" \ "mobile"
      } yield UserFoo(name, userVerified, mobileVerified)
      u.head
  }, Map.empty))


  implicit val formats = DefaultFormats + new UserFooSerializer

  parse(json).extractOpt[UserFoo] map {
    user =>
      println(user)
      // UserFoo(Bar,false,false)

      println(pretty(Extraction.decompose(user)))
      // {
      //   "name" : "Bar",
      //   "emailVerified" : false,
      //   "mobileVerified" : false
      // }
  }

}