通过 Scala 中的特征为枚举对象定义隐式格式

Defining implicit format for Enumeration objects via trait in Scala

我正在尝试为多个对象定义一个隐式特征,以便在反序列化枚举的 JSON 值时使用。我了解如何在一个对象中执行此操作,但我希望将此行为模板化以保持我的代码干燥。我可以通过执行以下操作来完成此操作:

object SomeEnum extends Enumeration {
  type SomeEnum = Value
  val FIRST: SomeEnum = Value("First")
  val SECOND: SomeEnum = Value("Second")
  implicit object SomeEnumFormat extends Format[SomeEnum] {
    def writes(o: SomeEnum): JsValue = JsString(o.toString)

    def reads(json: JsValue): JsResult[SomeEnum] = json match {
      case JsString(x) => JsSuccess(SomeEnum.withName(x.toLowerCase.capitalize))
      case _ => JsError()
    }
  }
}

以下是我一直在尝试的:

object SomeEnum extends Mappable {
  val FIRST: SomeEnum = Value("First")
  val SECOND: SomeEnum = Value("Second")
}

object SomeOtherEnum extends Mappable {
  val ABC: SomeOtherEnum = Value("Abc")
  val DEF: SomeOtherEnum = Value("Def")
}

trait Mappable extends Enumeration {
  implicit val enumMapper: JdbcType[Value] with BaseTypedType[Value] = MappedColumnType.base[Value,String](_.toString, this.withName)

  def unapply[Type](s: String): Option[Value] = values.find(s == _.toString)

  implicit object someFormat extends Format[Class[_ <: Mappable]] {
    def writes(o: Class[_ <: Mappable]): JsValue = JsString(o.toString)

    def reads(json: JsValue): JsResult[Value] = json match {
      case JsString(x) => JsSuccess(this.asInstanceOf[Mappable].withName(x.toLowerCase.capitalize))
      case _ => JsError()
    }
  }
}

我希望继承特征的行为与为 class 扩展特征提供隐式对象的模板版本相同,但我收到以下错误:

found   : Mappable#Value
required: Mappable.this.Value

如果我将读取的 return 类型设为 JsResult[Mappable#Value] 代码无法编译,因为没有找到指定枚举类型的隐式声明。任何帮助将不胜感激。

我最初误解了发生的事情,以下是有效的解决方案

object SomeEnum extends Mappable {
  type SomeEnum = Value
  val FIRST: SomeEnum = Value("First")
  val SECOND: SomeEnum = Value("Second")
}

object SomeOtherEnum extends Mappable {
  type SomeOtherEnum = Value
  val ABC: SomeOtherEnum = Value("Abc")
  val DEF: SomeOtherEnum = Value("Def")
}

trait Mappable extends Enumeration {
  implicit val enumMapper: JdbcType[Value] with BaseTypedType[Value] = MappedColumnType.base[Value,String](_.toString, this.withName)

  def unapply[Type](s: String): Option[Value] = values.find(s == _.toString)

  implicit object someFormat extends Format[Value] {
    def writes(o: Value): JsValue = JsString(o.toString)

    def reads(json: JsValue): JsResult[Value] = json match {
      case JsString(x) => JsSuccess(withName(x.toLowerCase.capitalize))
      case _ => JsError()
    }
  }
}