获取"没有找到类型为scala.concurrent.Future的Json序列化程序..." Scala Play应用程序中的异常

时间:2015-09-21 08:09:20

标签: json scala playframework-2.0

我正在尝试使用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}

4 个答案:

答案 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