组织与类型关联的Scala隐式
我想介绍一些类型,以更大的类型表示字段的可能值。该字段需要能够对JSON进行编码/解码,也能够写入/读取数据库 我还是Scala新手,我想要的类型是sum type Status=NotVerified | Correct | error。因为我希望每个构造函数都有一个字符串表示,所以我创建了一个带有字符串参数的密封case类,然后创建了扩展该case类的对象。为了能够编码/解码,我还需要隐式,但我不确定如何构造它。我可以将它们放在对象内部的新对象中,如下所示:组织与类型关联的Scala隐式,scala,implicit,circe,quill.io,Scala,Implicit,Circe,Quill.io,我想介绍一些类型,以更大的类型表示字段的可能值。该字段需要能够对JSON进行编码/解码,也能够写入/读取数据库 我还是Scala新手,我想要的类型是sum type Status=NotVerified | Correct | error。因为我希望每个构造函数都有一个字符串表示,所以我创建了一个带有字符串参数的密封case类,然后创建了扩展该case类的对象。为了能够编码/解码,我还需要隐式,但我不确定如何构造它。我可以将它们放在对象内部的新对象中,如下所示: sealed case clas
sealed case class Status(name: String)
object Status {
object NotVerified extends Status("not_verified")
object Correct extends Status("correct")
object Wrong extends Status("wrong")
object implicits {
implicit val encodeStatusJson: Encoder[Status] =
_.name.asJson
implicit val decodeStatusJson: Decoder[Status] =
Decoder.decodeString.map(Status(_))
implicit val encodeStatus: MappedEncoding[Status, String] =
MappedEncoding[Status, String](_.name)
implicit val decodeStatus: MappedEncoding[String, Status] =
MappedEncoding[String, Status](Status(_))
}
}
…然后在需要的地方显式导入这些,但这是非常…显式的
组织类型+隐式集合的好方法是什么?如果添加应用方法,则可以从字符串创建适当的状态,这将使解码器正常工作。把地位抽象化
sealed abstract class Status(name: String)
object Status {
object NotVerified extends Status("not_verified")
object Correct extends Status("correct")
object Wrong extends Status("wrong")
def apply(name: String): Status = name match {
case "not_verified" => NotVerified
case "correct" => Correct
case _ => Wrong
}
}
我认为您现有的隐式仍然有效,但我不知道那些特定的库…常用的方法是定义一个密封的特征: 或者是一个密封的抽象类,在当前的Scala版本中看起来可能更好:
sealed abstract class Status(val name: String)
object Status {
case object NotVerified extends Status("not_verified")
case object Correct extends Status("correct")
case object Wrong extends Status("wrong")
}
为了避免导入隐式,可以将它们直接放置在类型的伴随对象中。有关更多详细信息,请参见问题,特别是类型的伴随对象一节
是的,为这样的枚举定义隐式很容易重复。您必须求助于反射或宏。我建议使用这个库,它还集成了Circe和Quill。
以下是Circe的一个示例:
import enumeratum.values._
sealed abstract class Status(val value: String) extends StringEnumEntry {
def name: String = value
}
object Status extends StringEnum[Status] with StringCirceEnum[Status] {
val values = findValues
case object NotVerified extends Status("not_verified")
case object Correct extends Status("correct")
case object Wrong extends Status("wrong")
}
您可以使用它,而无需明确定义任何编码器/解码器或从Status导入任何内容:
您实现状态的方式有问题,因为您可以创建Statusnot\u verified,但类型将是Status而不是NotVerified,并且类型匹配不会给出正确的结果。你可以将状态抽象化,但我怀疑这会破坏解码器。@Tim Oh。你说得对!谢谢我真的不想要这里的子类型。我想我应该使用一个密封的特征,然后case类扩展它?但是quill/circe想要的解码器/编码器会非常重复……是的,这是进行简单枚举的正确方法。使状态抽象,并使用def applyname:String:Status=。。。它匹配字符串并返回相应的子类。然后Statusnot_verified将返回正确的基础类型。
import enumeratum.values._
sealed abstract class Status(val value: String) extends StringEnumEntry {
def name: String = value
}
object Status extends StringEnum[Status] with StringCirceEnum[Status] {
val values = findValues
case object NotVerified extends Status("not_verified")
case object Correct extends Status("correct")
case object Wrong extends Status("wrong")
}
scala> import io.circe.syntax._
scala> val status: Status = Status.Correct
status: Status = Correct
scala> status.asJson
res1: io.circe.Json = "correct"
scala> Decoder[Status].decodeJson(Json.fromString("correct"))
res2: io.circe.Decoder.Result[Status] = Right(Correct)