Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Play Json库中为单例提供隐式值_Json_Scala_Playframework_Scala Macros - Fatal编程技术网

在Play Json库中为单例提供隐式值

在Play Json库中为单例提供隐式值,json,scala,playframework,scala-macros,Json,Scala,Playframework,Scala Macros,我有以下配置: sealed trait Status case object Edited extends Status case object NotEdited extends Status case class Tweet(content:String, status:Status) 我想使用Play Json格式,所以我想我必须有这样的格式(我不想在companion对象中这样做): 但编译器抱怨说: 没有可用的推文隐式格式。 它还说我不能使用Edited.type,因为它需要ap

我有以下配置:

sealed trait Status
case object Edited extends Status
case object NotEdited extends Status

case class Tweet(content:String, status:Status)
我想使用Play Json格式,所以我想我必须有这样的格式(我不想在companion对象中这样做):

但编译器抱怨说:

没有可用的推文隐式格式。

它还说我不能使用
Edited.type
,因为它需要apply和unapply函数。我该怎么办

编辑1:

我能想到这样的事情:

implicit object StatusFormat extends Format[Status] {
    def reads(json: JsValue) =
      (json \ "type").get.as[String] match {
        case "" => Edited
        case _ => UnEdited
      }

    def writes(stat: Status) = JsObject(Seq(
      stat match {
        case Edited => "type" -> JsString("Edited")
        case NotEdited => "type" -> JsString("UnEdited")
      }
    ))
  }
  implicit object StatusFormat extends Format[Status] {
    def reads(json: JsValue) =
      json match {
        case JsString("Edited") => JsSuccess(Edited)
        case JsString("NotEdited") => JsSuccess(NotEdited)
        case _ => JsError("cannot parse it")
      }

    def writes(stat: Status) = JsString(stat.toString)
}

但是
read
部分有问题,编译器抱怨它需要JsonResult而不是
编辑。为此,键入

,我应该定义一个隐式对象,如下所示:

implicit object StatusFormat extends Format[Status] {
    def reads(json: JsValue) =
      (json \ "type").get.as[String] match {
        case "" => Edited
        case _ => UnEdited
      }

    def writes(stat: Status) = JsObject(Seq(
      stat match {
        case Edited => "type" -> JsString("Edited")
        case NotEdited => "type" -> JsString("UnEdited")
      }
    ))
  }
  implicit object StatusFormat extends Format[Status] {
    def reads(json: JsValue) =
      json match {
        case JsString("Edited") => JsSuccess(Edited)
        case JsString("NotEdited") => JsSuccess(NotEdited)
        case _ => JsError("cannot parse it")
      }

    def writes(stat: Status) = JsString(stat.toString)
}

使用函数式API也可以非常干净地执行此操作:

import play.api.data.validation.ValidationError
import play.api.libs.functional.syntax._
import play.api.libs.json._

implicit val StatusFormat: Format[Status] = Format(
  (__ \ 'type).read[String].collect[Status](ValidationError("Unknown status")) {
    case "UnEdited" => NotEdited
    case "Edited" => Edited
  },
  (__ \ 'type).write[String].contramap {
     case Edited => "Edited"
     case NotEdited => "UnEdited"
  }
)

implicit val TweetFormat: Format[Tweet] = Json.format[Tweet]

我发现这比手工实现
读取
写入
方法更清晰,主要是因为它突出了编码和解码之间的对称性。不过,这是一个品味的问题。

是不是真的有两个下划线(要记住这么多符号:)?对称性在哪里?(这几天试着学着“功能性地”打扮一下,你有什么建议或更好的吗?)。如果您不喜欢,可以编写
JsPath
。我也对操作符繁重的库表示怀疑,但Play JSON只有几个操作符,我认为它们非常合理。