问题描述
我从带有自定义主体的 singleRequest 中使用了一些数据,并且我尝试使用 Unmarshall 将其序列化为自定义 case 类,但它不起作用;身体反应是这样的:
{
"teams": [
{
"id": "21312","name": "team1","color": "#4169E1","avatar": null,"members": [
{
"user": {
"id": 12737636,"username": "user2","email": "user2@email.com","color": "#827718","profilePicture": null,"initials": "U2","role": 4,"custom_role": null,"last_active": "1613419183004","date_joined": "1612542647748","date_invited": "1612542548880"
},"invited_by": {
"id": 68732,"username": "user1","color": "#f8306d","email": "user1@email.com","initials": "U1","profilePicture": "https://attachments.clickup.com/profilePictures/image.jpg"
},"can_see_time_spent": true,"can_see_time_estimated": true,"can_see_points_estimated": true,"can_edit_tags": false
},{
"user": {
"id": 12715129,"username": "user3","email": "user3@email.com","color": "#04a9f4","initials": "IM","last_active": "1613483780281","date_joined": "1611598611255","date_invited": "1611597360856"
},"invited_by": {
"id": 4371505,"username": "user34","email": "user34@email.com","initials": "U34","can_edit_tags": false
}
]
}
]
}
val responseFuture = Http()
.singleRequest(HttpRequest( method = GET,uri = "https://apiRest/api/v2/team" )
.withHeaders(RawHeader("authorization","xxxxxxxxxxxx")))
我有这个案例类来序列化它:
case class Invited_By (id: Long,username:Option[String],color : Option[String],email: Option[String],initials : Option[String],profilePicture: Option[String])
case class User ( id: Long,username: Option[String],color: Option[String],profilePicture: Option[String],initials: Option[String],role: Option[Int],custom_role: Option[String],last_active: Option[String],date_joined: Option[String],date_invited: Option[String] )
case class Member (user: User,invited_By: Invited_By,can_see_time_spent: Boolean,can_see_time_estimated:Boolean,can_see_points_estimated:Boolean,can_edit_tags:Boolean)
case class Team (id : String,name: Option[String],avatar: Option[String],members: Seq[Member] )
case class Teams( teams: Seq[Team] )
我试过这个;这不起作用:
import play.api.libs.json._
import play.api.libs.functional.Syntax._
implicit val TeamsReads: Reads[Teams] = Json.reads[Teams]
val responseFuture = Http()
.singleRequest(HttpRequest( method = GET,"XXXXXXXXXXXX")))
.flatMap{
res =>
Unmarshal(res).to[String]
.map {
data =>
val jsValue:JsValue = Json.parse(data)
val result: JsResult[Teams] = jsValue.validate[Teams]
result
}
}
有更好的方法吗??
注意:我发现 akka-http-spray-json ,但我不知道如何实现它
解决方法
为了使用 akka-http-spray-json
,您需要导入这些库。
"com.typesafe.akka" %% "akka-http" % akkaHttpVersion, "com.typesafe.akka" %% "akka-http-spray-json" % akkaHttpVersion, "com.typesafe.akka" %% "akka-http-testkit" % akkaHttpVersion, "com.typesafe.akka" %% "akka-http2-support" % akkaHttpVersion,
然后按照以下步骤进行编组和解组 JSON 字符串。
- 步骤 1 - 导入喷雾 json
import spray.json._
- 第 2 步 - 创建 JSON 协议。
extends DefaultJsonProtocol
的特征。请注意,Chat
类有 4 个参数,因此我在协议中使用了jsonFormat4
。 - 第 3 步 - 扩展您创建的特征
- 第 4 步 - 添加 sprayJsonSupport
每次我需要向 akka 添加 json 支持时,我都会参考这个小例子:
import akka.actor.{Actor,ActorLogging,ActorSystem,Props}
import akka.http.scaladsl.Http
import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport
import akka.http.scaladsl.server.Directives._
import akka.pattern.ask
import akka.util.Timeout
import spray.json._ // step 1 - import spray json
import scala.concurrent.Future
import scala.concurrent.duration._
// case class Player(nickname: String,characterClass: String,level: Int)
case class Chat(sender: String,receiver: String,message: String,groupChatName: String)
case object GetAllUsersInChat
case class AddUsers(player: Chat)
// step 2 - the JSON protocol
trait ChatJsonProtocol extends DefaultJsonProtocol {
implicit val chatFormat = jsonFormat4(Chat)
}
class ChatActor extends Actor with ActorLogging {
var users = Map[String,Chat]()
override def receive: Receive = {
case GetAllUsersInChat =>
log.info(s"getting all users")
sender() ! users.values.toList
case AddUsers(user) =>
log.info(s"trying to add user $user")
users = users + (user.sender -> user)
case _ => log.info(s"unknown message")
}
}
// step 3 - extend ChatJsonProtocol
// step 4 - add sprayJsonSupport
object ChatMarshallingJSON extends ChatJsonProtocol with SprayJsonSupport {
implicit val system = ActorSystem("ChatMarshallingJSON")
val chatActor = system.actorOf(Props[ChatActor],"chatActor")
// boot strap some users
val chatusers = List(
Chat("sender1","receiver1","message1","groupChat1"), Chat("sender2","receiver2","message2","groupChat2"), Chat("sender3","receiver3","message3","groupChat3")
)
chatusers.foreach { user =>
chatActor ! AddUsers(user)
}
implicit val defaultTimeout = Timeout(2 seconds)
val chatRoutes = {
path("api" / "chat") {
get {
// 3: get all users in the chat
val allUsersInChatFuture: Future[List[Chat]] = (chatActor ? GetAllUsersInChat).mapTo[List[Chat]]
complete(allUsersInChatFuture)
}
}
}
def main(args: Array[String]): Unit = {
println("http GET localhost:8080/api/chat")
Http()
.newServerAt("localhost",8080)
.bindFlow(chatRoutes)
}
}