Scala,play - 无法从服务器

时间:2017-05-27 16:00:00

标签: scala playframework

我已经从rest api创建了一个简单的列表getter:

def list: Future[Iterable[ProductResource]] = {
    ProductService.listAllProducts.map { postDataList =>
      postDataList.map(postData => createProductResource(postData))
    }
  }

它使用此编写器将产品对象转换为json:

object ProductResource {
    implicit val implicitWrites = new Writes[Product] {
      def writes(product: Product): JsValue = {
        Json.obj(
          "id" -> product.id,
          "name" -> product.name,
          "description" -> product.description,
          "price" -> product.price,
          "amount" -> product.amount

        )
      }
    }
  }

但是当我编译项目时,我得到:play.sbt.PlayExceptions$CompilationException: Compilation error[Cannot use a method returning scala.concurrent.Future[Iterable[controllers.ProductController.ProductResource]] as a Handler for requests]我不明白如何修复它。 我查看了这个教程https://developer.lightbend.com/guides/play-rest-api/part-1/index.html 并且有类似的列表功能。

修改

我更新了这个功能并添加了一个动作:

def list: Action[AnyContent] = {
    Action.async { implicit request =>
      find.map { products =>
        Ok(Json.toJson(products))
      }
    }
  }


  def find: Future[Iterable[ProductResource]] = {
    ProductService.listAllProducts.map { postDataList =>
      postDataList.map(postData => createProductResource(postData))
    }
  }

现在我得到No Json serializer found for type Iterable[controllers.ProductController.ProductResource]. Try to implement an implicit Writes or Format for this type.,但我创建了一个写作。

2 个答案:

答案 0 :(得分:1)

您的控制器必须返回Future of JsValue(Future[JsValue])。 但是你正在返回ProductResource的Iterable(Iterable[ProductResource])。 将您的Iterable [ProductResource]转换为JsValue。

  • 将每个ProductResource对象转换为JsObject
  • 执行foldLeft操作以将JsObjects的序列转换为JsArray。
  • 使您导入的ProductResource类型为JsValue的隐式JsonWriter导入并在范围内可用。 (问题中显示的implicitWrites将产品转换为Json。控制器期望产品类型为ProductResource的JsonWriter)

这可以像下面这样完成。

import ProductResource.implicitWrites
import play.api.libs.json._

def list: Action[AnyContent] = Action.async { 
        find
         .map(x => Json.toJson(x))
         .map(x => x.foldLeft(JsArray())({case (acc, json) => acc :+ json})) 
         .map(x => Ok(x))
  }

答案 1 :(得分:0)

问题修复了ProdcutResource对象

中的更改
case class ProductResource(id: Option[Long], name: String, description: String, price: BigDecimal, amount: Int)

object ProductResource {
  implicit val implicitWrites = new Writes[ProductResource] {
    def writes(product: ProductResource): JsValue = {
      Json.obj(
        "id" -> product.id,
        "name" -> product.name,
        "description" -> product.description,
        "price" -> product.price,
        "amount" -> product.amount

      )
    }
  }
}

并且没有连接到json的错误。