Scala-如何实现隐式JSON阅读器

时间:2018-07-17 11:54:49

标签: json scala rest playframework playframework-2.2

我已经实现了隐式Json Reads,以便从JSON读取两个字段saleId和saleType。我想让getSales方法返回一个表示saleId和saleType的元组(Int,String)。但是,当我调用getSales方法时,出现以下错误:

Error:(46, 79) No JSON deserializer found for type (Int, String). Try to implement an implicit Reader or JsonFormat for this type.
    val salesData = (salesJson \ "sales").as[(Int, String)]

Error:(46, 79) not enough arguments for method as: (implicit reader: org.json4s.Reader[(Int, String)], implicit mf: Manifest[(Int, String)])(Int, String).
Unspecified value parameters reader, mf.
    val salesData = (salesJson \ "sales").as[(Int, String)]

我实现了隐式的Json Reads,因此确实与第一个错误混淆。这是我的实现:

def getsales(context: SparkContext, saleId: Int): (Int, String)= {
    val url= buildUrl(context, saleId)

    implicit val salesReader: Reads[(Int, String)] = (
      (__ \ "id_from_API").read[Int] and
        (__ \ "sale_type").read[String]
      ).tupled

    val salesJson: JValue = parse(httpStringResponse(url, context))
    val salesData = (salesJson \ "sales_stats").as[(Int, String)]

    salesData
}

1 个答案:

答案 0 :(得分:1)

与您的代码有关的两个注释:

#define

可能必须相同。

您可能希望将JsValue放在行中,而不是JValue

val salesData = (salesJson \ "sales").as[(Int, String)]
val salesData = (salesJson \ "sales_stats").as[(Int, String)]

除了将您的JSON阅读器代码与其余代码分开测试之外,其他方法可能会有所帮助。

以下对我有用:

val salesJson: JValue = parse(httpStringResponse(url, context))

请注意,此处使用的play-json版本为2.3.10。

编辑

注释中问题的代码示例

import org.scalatest.WordSpec
import play.api.libs.functional.syntax._
import play.api.libs.json._

class ReadsExample extends WordSpec {

  "read" in {
    val sales =
      """
          {
            "sales_stats": {
            "id_from_API": 42,
            "sale_type": "cheap"
          }
        }
        """.stripMargin

     implicit val salesReader: Reads[(Int, String)] = (
      (JsPath \ "id_from_API").read[Int] and
        (JsPath \ "sale_type").read[String]
      ).tupled

    val salesJson: JsValue = Json.parse(sales)
    val salesData = (salesJson \ "sales_stats").as[(Int, String)]
 }

}