【问题标题】:Handling Pk[Int] values in spray-json在 spray-json 中处理 Pk[Int] 值
【发布时间】:2013-12-25 16:18:15
【问题描述】:

[编辑]

所以,感谢Edmondo1984,我得到了一个快速而肮脏的解决方案,我不知道这是否是最好的解决方案。我不在 write 函数中处理带有模式匹配的空值。您可以在此编辑后阅读有关我的问题的更多详细信息。这是我现在的代码:

object DBNames extends DefaultJsonProtocol {



  implicit val pkFormat: JsonFormat[Pk[Int]] = new JsonFormat[Pk[Int]] {

    def write(obj: Pk[Int]): JsValue = JsNumber(obj.get)

    def read(json: JsValue): Pk[Int] = json.asJsObject.getFields("id") match {
      case Seq(JsNumber(id)) => new Pk[Int] { id.toInt }
      case _ => throw new DeserializationException("Int expected")
    }
  }

  implicit val nameFormat = jsonFormat2(Name)

jsonFormat2 将隐式使用 pkFormat 来解析 Pk[Int] 值。

在我的控制器类中,我有这个:

def listNames() = Action {
    val names = DBNames.findAll()
    implicit val writer = DBNames.nameFormat
    var json = names.toJson

    Ok(json.toString()).as("application/json")

}

我必须从我的模型中获取 nameFormat 并将其设为隐式,以便 bars.toJson 可以使用它来解析 Seq[Name] 名称。

[/edit]

我正在尝试使用 Play!带有 Scala 的框架,我是 Scala 编程和 Play 框架的新手,一切看起来都不错,但是我花了几个小时来解决这个问题,但没有找到解决方案。

我有一个案例类:

case class Name (id: Pk[Int], name: String)

还有一个对象来处理MySql。我创建了一个implicit val nameFormat = jsonFormat2(Name) 来处理 JSON。

object DBNames extends DefaultJsonProtocol {

  implicit val nameFormat = jsonFormat2(Name)

  var parser =
  {
    get[Pk[Int]]("id") ~
    get[String]("name")  map {
      case id ~ name =>  Name(id,name)
    }
  }

  def findAll():Seq[Name] =
  {
     DB.withConnection {
       implicit connection =>
         SQL("select * from names").as(DBNames.parser *)
     }

  }

  def create(name: Name){
    DB.withConnection {
      implicit connection =>
        SQL("insert into names (name) values ({name})").on(
          'name -> name.name
        ).executeUpdate()
    }
  }


}

但是当我尝试编译它时,Play!给我这个结果:

[error] D:\ProjetosJVM\TaskList\app\models\Names.scala:20: could not find implicit value for evidence parameter of type models.DBNames.JF[anorm.Pk[Int]]

他似乎找不到解析 id 值的方法,因为它是一个 Pk[Int] 值。

因此,通过阅读以下内容:https://github.com/spray/spray-json 我没有找到一种方法来解析它,而无需像文档中显示的那样创建完整的对象解析器:

object MyJsonProtocol extends DefaultJsonProtocol {
  implicit object ColorJsonFormat extends RootJsonFormat[Color] {
    def write(c: Color) = JsObject(
      "name" -> JsString(c.name),
      "red" -> JsNumber(c.red),
      "green" -> JsNumber(c.green),
      "blue" -> JsNumber(c.blue)
    )
    def read(value: JsValue) = {
      value.asJsObject.getFields("name", "red", "green", "blue") match {
        case Seq(JsString(name), JsNumber(red), JsNumber(green), JsNumber(blue)) =>
          new Color(name, red.toInt, green.toInt, blue.toInt)
        case _ => throw new DeserializationException("Color expected")
      }
    }
  }
}

我有一个“大”(实际上是小)项目,我想让大部分事情都使用 Ajax,所以我认为这不是一个好方法。

我如何处理这个项目中的 JSON 对象,其中几乎所有 case classes 都将有一个“JSON 解析器”,而无需像上面的 sn-p 那样创建大量代码?还有,我怎样才能使它与Seq[Name] 一起工作?

【问题讨论】:

    标签: json scala playframework


    【解决方案1】:

    您不需要编写完整的解析器。编译器说:

    [error] D:\ProjetosJVM\TaskList\app\models\Names.scala:20: could not find implicit 
    
    value for evidence parameter of type models.DBNames.JF[anorm.Pk[Int]]
    

    scala 编译器正在寻找JF[anorm.Pk[Int]] 类型的隐式参数,并且在范围内没有这样的隐式参数。 JF[anorm.Pk[Int]] 是什么?好吧,你需要知道这个库而我没有,所以我浏览了spray-json 的源代码并发现:

    trait StandardFormats {
      this: AdditionalFormats =>
    
      private[json] type JF[T] = JsonFormat[T] // simple alias for reduced verbosity
    

    所以JF[T] 只是JsonFormat[T] 的别名。这一切都说得通:PK[Int] 是一个来自Anorm 的类,spray-json 为标准类型提供开箱即用的 json 支持,但甚至不知道 Anorm 存在所以你必须编码你的支持为Pk[Int] 并使其隐含在范围内。

    您将拥有如下代码:

    object DBNames extends DefaultJsonProtocol {
    
       implicit val pkFormat : JsonFormat[Pk[Int]] = new JsonFormat[Pk[Int]] {
          //implementation
       }
       // rest of your code
    }
    

    如果您刚开始使用 Scala,您可能需要阅读有关隐式及其解析的更多信息。我为您提供了一个最低限度的答案:一旦您提供了正确的实现,您的代码就会编译。我建议您参考 anorm.Pk 和 JsonFormat 的 javadoc,以了解如何为您的类型正确实现它。

    Pk 看起来像 scala.Option,在 spray-json 内的 StandardFormats 源代码中,您可以找到 Option 的 JsonFormat 实现,您可以从中复制

    【讨论】:

    • 谢谢,埃德蒙多。我真的必须阅读更多关于隐式的内容,它们就像魔术一样工作。如果未提供变量但可以从范围内的隐式中获取,则将使用它们。这就是他们的样子。 jsonFormat2 不知道如何解析Pk[Int],但他知道有一个名为pkFormat 的值知道如何解析,所以他会使用它。
    猜你喜欢
    • 2015-07-27
    • 2013-03-22
    • 2015-03-31
    • 1970-01-01
    • 2018-08-02
    • 1970-01-01
    • 2015-10-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多