我正在尝试使用Scala Play 2,Slick 3和PostgreSQL的Web应用程序。我的目的是从控制器返回JSON。
这些是依赖关系 -
libraryDependencies ++= Seq(
"org.postgresql" % "postgresql" % "9.4-1201-jdbc41",
"com.typesafe.slick" %% "slick" % "3.0.0",
"com.typesafe.play" %% "play-slick" % "1.0.1",
"com.typesafe.play" %% "play-slick-evolutions" % "1.0.1",
specs2 % Test
)
这是我的模特之一 -
package models
import play.api.libs.json.Json
import slick.driver.PostgresDriver.api._
import play.api.mvc._
import play.api.libs.json._
import play.api.libs.functional.syntax._
case class User (id: String, name: String)
class UserModel (tag: Tag) extends Table[User](tag, "USERS") {
def id = column[String]("ID", O.PrimaryKey)
def email = column[String]("EMAIL")
def * = (id, email) <> (User.tupled, User.unapply _)
}
object Users extends ModelInit {
lazy val users = TableQuery[UserModel]
implicit val userFormat = Json.format[User]
def all = {
db.run(users.result)
}
}
这是我的控制器 -
package controllers
import models.Users
import play.api.libs.json.Json
import play.api.mvc._
class Application extends Controller {
def index = Action {
val users = Users.all
val json = Json.toJson(users)
println(json)
Ok(views.html.index("Your new application is ready."))
}
}
目前我正在接受以下异常 -
No Json serializer found for type scala.concurrent.Future[Seq[models.UserModel#TableElementType]]. Try to implement an implicit Writes or Format for this type.
class Application extends Controller {
8 def index = Action {
9 val users = Users.all
10 val json = Json.toJson(users)
11 println(json)
12 Ok(views.html.index("Your new application is ready."))
13 }
14}
答案 0 :(得分:0)
你需要做这样的事情:
class Application extends Controller {
def index = Action {
val users = Users.all
users.map(js => println(Json.toJson(js))) // this will give you Future[Unit] but instead of printing you can simply get Future[Json], i.e you can map one future into another future.
Ok(views.html.index("Your new application is ready."))
}
}
或
您可以等待未来(不推荐),然后将其序列化。
import concurrent.duration._
val users = Await.result(Users.all,5.seconds)
val json = Json.toJson(users)
println(json)
PS:我没有测试过,但这似乎是解决方案。
答案 1 :(得分:0)
你正在尝试序列化Future(花哨的回调)。 Future表示很快就能获得的数据,但现在却不是。您可以使用getView(0,null,parent);
或map
(如果它是嵌套的,google monads以获取更多详细信息)转换所需的期货内容。
所以要解决它。
flatMap
虽然该代码阻止了您的线程。我建议使用 def index = Action {
val users = Users.all
val json = Json.toJson(users)
json.map{ actualJson=>
//do something fancy
}
Ok(views.html.index("Your new application is ready."))
}
这是Action的异步版本。它非常相似,但它要求您返回Action.async
。这很简单。
Future[Result]
答案 2 :(得分:0)
将Json格式化程序移动到控制器解决了这个问题。
我目前的模特 -
package models
import play.api.libs.json.Json
import slick.driver.PostgresDriver.api._
import scala.concurrent.Future
case class User(id: String, name: String)
object Users extends ModelInit {
class UserModel(tag: Tag) extends Table[User](tag, "USERS") {
def id = column[String]("ID", O.PrimaryKey)
def email = column[String]("EMAIL")
def * = (id, email) <> (User.tupled, User.unapply)
}
lazy val users = TableQuery[UserModel]
def all = {
db.run(users.result)
}
def create(user: User): Future[Int] = {
db.run(users += user)
}
def getById(name: String) = {
val selectQuery = users.map(_.id)
val selectAction = selectQuery.result
db.run(selectAction)
}
}
目前的控制器 -
package controllers
import models.Users
import play.api.mvc._
import play.api.libs.concurrent.Execution.Implicits._
import play.api.libs.json._
class Application extends Controller {
def index = Action {
implicit val userFormat = Json.format[UserModel]
Users.all.map(user => println(Json.toJson(user)))
Ok(views.html.index("Your new application is ready."))
}
}
答案 3 :(得分:0)
我正在使用typesafe-activator播放scala + slick并且遇到了同样的问题。如果JSON自动映射正在使用我不确定的伴随对象,那么为什么它找不到格式化器是有道理的。将格式化程序移动到像ASDF这样的控制器上说并修复了现在的问题,但我觉得在模型文件中仍然会更好
https://www.playframework.com/documentation/2.5.x/ScalaJsonAutomated
http://slick.lightbend.com/doc/3.0.0/schemas.html#mapped-tables