如何将这个JSON解析为Map [String,User]?

时间:2014-08-26 01:09:31

标签: json scala playframework

我想从以下JSON开始:

[
  {
    "name": "Cat",
    "profile_image_url": "http://a0.twimg.com/profile_images/2284174872/7df3h38zabcvjylnyfe3_normal.png",
    "location": "San Francisco, CA",
    "id_str": "799346"
  },
  {
    "name": "Dog",
    "profile_image_url": "http://a0.twimg.com/profile_images/2284174758/v65oai7fxn47qv9nectx_normal.png",
    "location": "San Francisco, CA",
    "id_str": "783214"
  }
]

Map[String, User],其中键是名称,User是这样的对象:

case class User(name: String, profileImage: String, id: String) 

我正在使用Play和Scala,但我正在努力弄清楚如何进行JSON解析。

3 个答案:

答案 0 :(得分:1)

首先,您可以为您的类型定义Reads类型类的实例:

import play.api.libs.functional.syntax._
import play.api.libs.json._

implicit val userReads = (
  (__ \ 'name).read[String] and
  (__ \ 'profile_image_url).read[String] and
  (__ \ 'id_str).read[String]
)(User.apply _)

然后你得到一个免费的Reads[List[User]]实例,它将解码你的JSON:

Json.parse(jsonString).validate[List[User]]

这不完全是您想要的,但您可以很容易地将列表转换为地图:

Json.parse(jsonString).validate[List[User]].map(_.map(u => u.name -> u).toMap)

现在你已经有JsResult[Map[String, User]]

答案 1 :(得分:0)

或者,也许你可以使用argonaut,它提供更友好的api。

val json: String = """[
                     {
                       "name": "Cat",
                       "profile_image_url": "http://a0.twimg.com/profile_images/2284174872/7df3h38zabcvjylnyfe3_normal.png",
                       "location": "San Francisco, CA",
                       "id_str": "799346"
                     },
                     {
                       "name": "Dog",
                       "profile_image_url": "http://a0.twimg.com/profile_images/2284174758/v65oai7fxn47qv9nectx_normal.png",
                       "location": "San Francisco, CA",
                       "id_str": "783214"
                     }
                   ]"""

      import argonaut._, Argonaut._

      case class User(name: String, url: String, location: String, idStr: String)
      implicit def UserCodecJson =
        casecodec4(User.apply, User.unapply)("name", "profile_image_url", "location", "id_str")

      val result = json.decodeValidation[List[User]]

      println(result) //Success(List(User(Cat,http://a0.twimg.com/profile ....

这个结果的好处是Scalaz Validation,因为验证是monad,所以你可以将它与其他验证绑定(flatmap)。

答案 2 :(得分:0)

您可以尝试这种方式:

1使用格式定义Case类:

case class User(name: String, profileImage: String, id: String) {
    implicit val jsonFormat: Format[User] = Json.format[User]
}    

2将您的json解析为List [User]

val jsonStr: String = ...
val users = Json.parse(jsonStr).as[List[User]]

3将您的列表[用户]分组到地图[字符串,用户]

val whatYourWant:Map[String, User] = users.groupBy(_.name)