如何将JSON解析为映射[String, User]?

时间:2023-01-06 17:03:24

I want to go from the following JSON:

我想从下面的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"
  }
]

to a Map[String, User], where the key is the name, and the User is the object that looks like this:

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

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

I'm using Play and Scala but am struggling to figure out how to do the JSON parsing.

我使用的是Play和Scala,但我很难弄清楚如何进行JSON解析。

3 个解决方案

#1


1  

First you can define an instance of the Reads type class for your type:

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

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

And then you get a Reads[List[User]] instance for free that will decode your JSON:

然后你会得到一个读取[List[User]]]]的实例,它会解码你的JSON:

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

That's not exactly what you want, but you can turn the list into a map pretty easily:

这不是你想要的,但是你可以很容易地把列表变成一张地图:

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

And now you've got a JsResult[Map[String, User]].

现在您有了一个JsResult[Map[String, User]]]。

#2


0  

Alternatively, maybe you can use argonaut, it provides more friendly api.

或者,您可以使用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 ....

The good thing about this result is Scalaz Validation, because Validation is monad, so you can bind (flatmap) it with other Validation.

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

#3


0  

You can try this way:

你可以这样尝试:

1 Define you Case class with format:

1用格式定义你的Case类:

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

2 parsing your json as List[User]

2将json解析为列表[用户]

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

3 group your List[User] to Map[String, User]

3组您的列表[用户]映射[String, User]

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

#1


1  

First you can define an instance of the Reads type class for your type:

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

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

And then you get a Reads[List[User]] instance for free that will decode your JSON:

然后你会得到一个读取[List[User]]]]的实例,它会解码你的JSON:

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

That's not exactly what you want, but you can turn the list into a map pretty easily:

这不是你想要的,但是你可以很容易地把列表变成一张地图:

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

And now you've got a JsResult[Map[String, User]].

现在您有了一个JsResult[Map[String, User]]]。

#2


0  

Alternatively, maybe you can use argonaut, it provides more friendly api.

或者,您可以使用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 ....

The good thing about this result is Scalaz Validation, because Validation is monad, so you can bind (flatmap) it with other Validation.

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

#3


0  

You can try this way:

你可以这样尝试:

1 Define you Case class with format:

1用格式定义你的Case类:

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

2 parsing your json as List[User]

2将json解析为列表[用户]

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

3 group your List[User] to Map[String, User]

3组您的列表[用户]映射[String, User]

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