如何使用 circe 将密封的特征案例对象转换为字符串



我正在使用Scala和Circe。我有以下密封特征。

sealed trait Mode
case object Authentication extends Mode
case object Ocr extends Mode

调用SessionModel.Authentication时,此 case 对象的输出如下所示:

"Authentication":{}

我需要将其转换为字符串,以便它输出"authentication"

正如Andriy Plokhotnyuk上面指出的,你可以使用circe-generic-extras:

import io.circe.Codec
import io.circe.generic.extras.Configuration
import io.circe.generic.extras.semiauto.deriveEnumerationCodec
sealed trait Mode
case object Authentication extends Mode
case object Ocr extends Mode
object Mode {
private implicit val config: Configuration =
Configuration.default.copy(transformConstructorNames = _.toLowerCase)
implicit val modeCodec: Codec[Mode] = deriveEnumerationCodec[Mode]
}

然后:

scala> import io.circe.syntax._
import io.circe.syntax._
scala> (Authentication: Mode).asJson
res1: io.circe.Json = "authentication"
scala> io.circe.Decoder[Mode].decodeJson(res1)
res2: io.circe.Decoder.Result[Mode] = Right(Authentication)

(请注意,Codec0.12 中的新功能 - 对于早期版本,您必须像 Andriy 的评论中那样写出这两个实例。

但是,除非您有很多要维护的实例,否则我个人认为手动编写实例通常比使用circe-generic-extras更好,在这种情况下,它甚至不会更冗长:

import io.circe.{Decoder, Encoder}
sealed trait Mode
case object Authentication extends Mode
case object Ocr extends Mode
object Mode {
implicit val decodeMode: Decoder[Mode] = Decoder[String].emap {
case "authentication" => Right(Authentication)
case "ocr"            => Right(Ocr)
case other            => Left(s"Invalid mode: $other")
}
implicit val encodeMode: Encoder[Mode] = Encoder[String].contramap {
case Authentication => "authentication"
case Ocr            => "ocr"
}
}

它的工作原理与deriveEnumerationCodec版本完全相同,但除了 circe-core 之外不需要任何东西,不那么神奇,编译速度更快,等等。 泛型推导对于具有简单映射的简单案例类非常有用,但我认为人们经常尝试将其扩展以涵盖所有情况,因为手动编写实例不会造成太大负担,甚至可能更清晰。

最新更新