问题描述
我正在尝试通过Scala中的akka库从本地服务器检索一些数据。 数据以JSON格式从服务器返回,但是我无法以自定义类型将其解组。
自定义类是个人资料,其中包含个人资料列表。
case class Profile(
Name: String,Surname: String,Mail: String,Age: Int,Town: String,Role: String,PrimaryInstr: String,SecondaryInstr: String,PrimaryGenre: String,SecondaryGenre: String,Influences: String,RecordLabel: String,GigAvailability: String,RehearseAvailability: String,RecordingExperience: String,MusicalAge: Int)
case class Profiles(profiles: Vector[Profile])
我尝试使用以下代码解组到“个人档案”,但是无法编译 由于错误
找不到参数um的隐式值:akka.http.scaladsl.unmarshalling.Unmarshaller [ResponseEntity,Profiles]
import akka.http.scaladsl.Http
import akka.http.scaladsl.unmarshalling.Unmarshal
import akka.http.scaladsl.client.RequestBuilding.Get
import akka.http.scaladsl.model.HttpResponse
...
def getProfiles = {
var req = Get("http://localhost:9090/profiles")
val responseFuture: Future[HttpResponse] = Http().singleRequest(req)
responseFuture
.onComplete {
case Success(response) =>
println(response.entity)
//Here I want actually Unmarshall to Profiles,not to String
var responseAsstring = Unmarshal(response.entity).to[String] //Tried here with Profiles
println(responseAsstring)
case Failure(_) => sys.error("something wrong")
}
...
}
使用[String]解组代码会产生此输出(缩写为“ ...”)。
httpentity.Strict(application / json,[{“ Name”:“ Amadeus”,“ Surname”:“ Rapisarda”,...,“ MusicalAge”:9},{“ Name”:“ Federico”,“姓“:” D'Ambrosio“,...,” MusicalAge“:24}]) FulfilledFuture([{“ Name”:“ Amadeus”,“ Surname”:“ Rapisarda”,...,“ MusicalAge”:9},{“ Name”:“ Federico”,“ Surname”:“ D'Ambrosio”, ...,“ MusicalAge”:24}])
如何获取个人档案对象? 预先感谢!
解决方法
我终于找到了行之有效的解决方案。
1-将这些依赖项添加到build.sbt文件中
val AkkaVersion = "2.6.9"
val AkkaHttpVersion = "10.2.0"
libraryDependencies ++= Seq(
"com.typesafe.akka" %% "akka-actor-typed" % AkkaVersion,"com.typesafe.akka" %% "akka-stream" % AkkaVersion,"com.typesafe.akka" %% "akka-http" % AkkaHttpVersion,"com.typesafe.akka" %% "akka-http-spray-json" % AkkaHttpVersion
)
2-在文件中添加这些导入
import akka.actor.typed.ActorSystem
import akka.actor.typed.scaladsl.Behaviors
import akka.http.scaladsl.Http
import akka.http.scaladsl.client.RequestBuilding.Get
import akka.http.scaladsl.model.{HttpResponse,StatusCodes}
import akka.http.scaladsl.unmarshalling.Unmarshal
import scala.util.{Failure,Success}
// for JSON serialization/deserialization following dependency is required:
// "com.typesafe.akka" %% "akka-http-spray-json" % "10.1.7"
import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport._
import spray.json.DefaultJsonProtocol._
import scala.concurrent.Future
3-定义您的自定义模型(在我的情况下,仅是个人档案模型)
final case class Profile(
Name: String,Surname: String,Mail: String,Age: Int,Town: String,Role: String,PrimaryInstr: String,SecondaryInstr: String,PrimaryGenre: String,SecondaryGenre: String,Influences: String,RecordLabel: String,GigAvailability: String,RehearseAvailability: String,RecordingExperience: String,MusicalAge: Int)
4-定义自定义“ unmarshaller”:计算自定义模型的属性数量,例如 n 并使用jsonFormat n ( 您的CustomType )。因此,在这种情况下,我们有16个属性->
implicit val profileFormat = jsonFormat16(Profile)
5-发出http请求。确保您的响应包含与模型匹配的JSON对象或objetcs的JSON数组。使用此代码检索响应并将其转换为您的自定义模型。
def getProfiles = {
//Make request
var req = Get("http://localhost:9090/profiles")
//Save Response in a Future object
val responseFuture: Future[HttpResponse] = Http().singleRequest(req)
//When the Future is fulfilled
responseFuture.onComplete {
case Success(response) =>
//Here your code if there is a response
//Convert your response body (response.entity) in a profile array. Note that it is a Future object
var responseAsProfiles: Future[Array[Profile]]= Unmarshal(response.entity).to[Array[Profile]]
//When the Future is fulfilled
responseAsProfiles.onComplete{
_.get match {
case profiles: Array[Profile] =>
//If response was a array of Profiles you can work with profiles
profiles.foreach[Profile] { profile =>
println(profile)
profile
}
case _ => println("error")
}
}
case Failure(_) =>
//Here your code if there is not a response
sys.error("something wrong")
}
}
希望这将对某人有所帮助!再见!