【问题标题】:Scala, play - cannot return list from serverScala,播放 - 无法从服务器返回列表
【发布时间】:2017-05-28 03:02:56
【问题描述】:

我从 rest api 创建了一个简单的列表获取器:

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

它使用这个 writer 将产品对象转换为 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.,但我创建了一个 writes。

【问题讨论】:

    标签: scala playframework


    【解决方案1】:

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

    • 将每个单独的 ProductResource 对象转换为 JsObject
    • 执行foldLeft 操作将JsObject 序列转换为JsArray。
    • 让你的隐式 JsonWriter 将ProductResource 类型转换为 JsValue 被导入并在范围内可用。 (问题中显示的implicitWrites 将Product 转换为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))
      }
    

    【讨论】:

    【解决方案2】:

    问题修复了我对 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 的错误。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-05-13
      • 1970-01-01
      • 1970-01-01
      • 2021-12-21
      • 1970-01-01
      • 1970-01-01
      • 2016-07-30
      • 1970-01-01
      相关资源
      最近更新 更多