0

我正在尝试在 Play2 中实现一个控制器,它为我的数据库表公开了一个简单的 REST 样式的 api。我使用squeryl进行数据库访问,并使用spray-json 将对象转换为 json

我的想法是有一个通用控制器来完成所有的工作,所以我在中设置了以下路线conf/routes

GET  /:tableName              controllers.Crud.getAll(tableName)
GET  /:tableName/:primaryKey  controllers.Crud.getSingle(tableName, primaryKey)

..和以下控制器:

object Crud extends Controller {
    def getAll(tableName: String) = Action {..}
    def getSingle(tableName: String, primaryKey: Long) = Action {..}
}        

(是的,缺少创建/更新/删除,但让我们先阅读工作)

我已经通过扩展的 squeryl 将表映射到案例类Schema

object MyDB extends Schema {
    val accountsTable = table[Account]("accounts")
    val customersTable = table[Customer]("customers")
}

我已经告诉 spray-json 我的案例类,所以它知道如何转换它们。

object MyJsonProtocol extends DefaultJsonProtocol {
  implicit val accountFormat = jsonFormat8(Account)
  implicit val customerFormat = jsonFormat4(Customer)    
}

到目前为止一切顺利,只要我直接使用表实例,它实际上工作得很好。当我尝试生成代码时,问题就出现了,这样我最终得到了一个用于访问所有表的控制器:我遇到了一些无法编译的代码,我不确定下一步是什么。

这似乎是 spray-json 的类型问题,当我试图在我的getAll函数中将对象列表转换为 json 时会发生这种问题。

这是我的一般尝试:

def getAll(tableName: String) = Action {

  val json = inTransaction {

    // lookup table based on url
    val table = MyDB.tables.find( t => t.name == tableName).get  

    // execute select all and convert to json
    from(table)(t =>
      select(t)
    ).toList.toJson // causes compile error
  }

  // convert json to string and set correct content type
  Ok(json.compactPrint).as(JSON)
}

编译错误:

[error] /Users/code/api/app/controllers/Crud.scala:29: 
Cannot find JsonWriter or JsonFormat type class for List[_$2]
[error]       ).toList.toJson
[error]                ^
[error] one error found

我猜这个问题可能是 json-library 需要在编译时知道我要扔给它的模型类型,但我不确定(注意List[_$2]那个编译错误)。我已尝试对编译并返回结果的代码进行以下更改:

  1. 删除通用的表查找 ( MyDB.tables.find(.....).get) 并改用特定的表实例,例如MyDB.accountsTable. 证明 JSON 序列化工作但是,这不是通用的,需要一个唯一的控制器和 db 中每个表的路由配置
  2. 在调用 toJson 之前将对象列表从 db 查询转换为字符串。即:toList.toJson--> toList.toString.toJson证明表的通用查找有效但不是正确的 json 响应,因为它是字符串序列化的对象列表。

有人想吗?

4

1 回答 1

1

你的猜测是正确的。MyDb.tables 是一个 Seq[Table[_]],换句话说,它可以保存任何类型的表。编译器无法确定您使用 find 方法找到的表的类型,并且似乎 JSON 转换需要该类型。有一些方法可以解决这个问题,但您需要对模型类进行某种类型的访问。

于 2014-01-07T17:19:50.343 回答