Reads [T]定义中的一个JsPath.read无法编译。两个或两个以上

时间:2017-11-18 20:25:57

标签: json scala playframework

使用play.api.libs.json库,只要使用单个Reads[T]表达式,我就无法创建JsPath.read对象。

在下面的代码中,仅当Reads[T]定义使用两个或更多JsPath.read个表达式时,我才能读取文件。只使用一个,我得到以下编译器错误:

Error:(33, -1) Play 2 Compiler: 
 C:\..\data\JsonReads.scala:33:25: overloaded method value read with alternatives:
   (t: Int)play.api.libs.json.Reads[Int] 
   (implicit r: play.api.libs.json.Reads[Int])play.api.libs.json.Reads[Int]

Error:(41, -1) Play 2 Compiler: 
 C:\..\data\JsonReads.scala:41:20: overloaded method value read with alternatives:
   (t: JsonReads.Two)play.api.libs.json.Reads[JsonReads.Two] 
   (implicit r: play.api.libs.json.Reads[JsonReads.Two])play.api.libs.json.Reads[JsonReads.Two]

为什么我会收到这些编译错误?

import play.api.libs.functional.syntax._
import play.api.libs.json.{JsValue, _}

import scala.io.Source

/**
  * one.json:
  * {
  * "one" : 1
  * }
  *
  * two.json:
  * {
  * "one" : 1,
  * "two" : 2
  * }
  *
  * two.single.json:
  * {
  * "a" : {
  * "one": 1,
  * "two": 2
  * }
  * }
  *
  * two.double.json
  * {
  * "a": {
  * "one": 1,
  * "two": 2
  * },
  * "b": {
  * "one": 1,
  * "two": 2
  * }
  * }
  *
  */

object JsonReads {

  case class One(one: Int)

  case class Two(one: Int, two: Int)

  case class SingleTwo(a: Two)

  case class DoubleTwo(a: Two, b: Two)

  // THIS WILL NOT COMPILE
  //  implicit val oneReads: Reads[One] = (
  //    (__ \ "one")).read[Int](One)

  implicit val twoReads: Reads[Two] = (
    (__ \ "one").read[Int] ~
      (__ \ "two").read[Int]) (Two)

  // THIS WILL NOT COMPILE
  //  implicit val singleTwoReads: Reads[SingleTwo] = (
  //    (__ \ "a").read[Two]) (SingleTwo)

  implicit val doubleTwoReads: Reads[DoubleTwo] = (
    (__ \ "a").read[Two] ~
      (__ \ "b").read[Two]
    ) (DoubleTwo)

  def load(name: String): JsValue = {
    val url = getClass.getResource(s"/data/${name}.json")
    val reader = Source.fromURL(url).bufferedReader
    val text = reader.lines.toArray.mkString("")
    Json.parse(text)
  }

  def main(a: Array[String]): Unit = {

    val oneJsValue: JsValue = load("one")
    /*    oneJsValue.validate[One](oneReads) match {
          case s: JsSuccess[One] => println(s"Found: ${s.get.toString}")
          case e: JsError => println("Errors: " +     JsError.toJson(e).toString())
        } */

    val twoJsValue: JsValue = load("two")
    twoJsValue.validate[Two](twoReads) match {
      case s: JsSuccess[Two] => println(s"Found: ${s.get.toString}")
      case e: JsError => println("Errors: " + JsError.toJson(e).toString())
    }

    val singleTwoJsValue: JsValue = load("two.single")
    /*    twoJsValue.validate[SingleTwo](singleTwoReads) match {
          case s: JsSuccess[SingleTwo] => println(s"Found:     ${s.get.toString}")
          case e: JsError => println("Errors: " +     JsError.toJson(e).toString())
        } */

    val doubleTwoJsValue: JsValue = load("two.double")
    doubleTwoJsValue.validate[DoubleTwo](doubleTwoReads) match {
      case s: JsSuccess[DoubleTwo] => println(s"Found: ${s.get.toString}")
      case e: JsError => println("Errors: " + JsError.toJson(e).toString())
    }

  }


}

1 个答案:

答案 0 :(得分:0)

Reads是一个仿函数。所以正确的代码是

implicit val oneReads: Reads[One] = (__ \ "one").read[Int].map(One)

implicit val singleTwoReads: Reads[SingleTwo] = (__ \ "a").read[Two].map(SingleTwo)

测试:

def main(a: Array[String]): Unit = {

  val oneJsValue: JsValue = load("one")
  oneJsValue.validate[One](oneReads) match {
    case s: JsSuccess[One] => println(s"Found: ${s.get.toString}")
    case e: JsError => println("Errors: " + JsError.toJson(e).toString())
  } // Found: One(1)

  val twoJsValue: JsValue = load("two")
  twoJsValue.validate[Two](twoReads) match {
    case s: JsSuccess[Two] => println(s"Found: ${s.get.toString}")
    case e: JsError => println("Errors: " + JsError.toJson(e).toString())
  } // Found: Two(1,2)

  val singleTwoJsValue: JsValue = load("two.single")
  singleTwoJsValue.validate[SingleTwo](singleTwoReads) match {
    case s: JsSuccess[SingleTwo] => println(s"Found: ${s.get.toString}")
    case e: JsError => println("Errors: " + JsError.toJson(e).toString())
  } // Found: SingleTwo(Two(1,2))

  val doubleTwoJsValue: JsValue = load("two.double")
  doubleTwoJsValue.validate[DoubleTwo](doubleTwoReads) match {
    case s: JsSuccess[DoubleTwo] => println(s"Found: ${s.get.toString}")
    case e: JsError => println("Errors: " + JsError.toJson(e).toString())
  } // Found: DoubleTwo(Two(1,2),Two(1,2))

}

https://www.playframework.com/documentation/2.6.x/ScalaJsonCombinators#Path-Reads