Circe 和 Scala 的枚举类型
Circe and Scala's Enumeration type
我正在努力思考 Circe。
所以,这是我得到的模型:
object Gender extends Enumeration {
type Gender = Value
val Male, Female, Unisex, Unknown = Value
}
case class Product(id: String, gender: Gender.Value)
我要
a) 将这个简单示例编码为 JSON 字符串
val product = Product(id = "1234", gender = Gender.Female)
b) 将结果 JSON 映射回产品案例 class.
我自己的尝试并没有让我走得太远:
object JsonProtocol {
implicit val productDecoder: Decoder[Product] = deriveDecoder
implicit val productEncoder: Encoder[Product] = deriveEncoder
}
导致编译时错误
Error:(52, 49) could not find Lazy implicit value of type io.circe.generic.decoding.DerivedDecoder[A]
implicit val productDecoder: Decoder[Product] = deriveDecoder
^
我不知道为什么会抛出这个异常,也不知道解决方案是什么样的。也许是枚举类型的用法?但是,我只是猜测。
尝试使用以下方法为枚举定义您自己的编码器和解码器:
Decoder.enumDecoder[E <: Enumeration](enum: E)
Encoder.enumEncoder[E <: Enumeration](enum: E)
类似于:
object JsonProtocol {
implicit val genderDecoder: Decoder[Gender.Value] = Decoder.enumDecoder(Gender)
implicit val genderEncoder: Encoder[Gender.Value] = Encoder.enumEncoder(Gender)
implicit val productDecoder: Decoder[Product] = deriveDecoder
implicit val productEncoder: Encoder[Product] = deriveEncoder
}
这些是必需的,因为据我所知,automatic/semiautomatic 派生程序仅适用于 sealed trait
和 case classes
的层次结构。您看到该错误的原因是因为 Product
的派生编解码器将隐式要求 encoders/decoders 每个参数的类型。 String
的 encoder/decoder 是 Circe 的标准部分,但您可能需要为自己的枚举创建一个。
如果您想在 circe 中使用枚举,请查看 enumeratum。然后你可以尝试这样的事情:
import enumeratum._
sealed trait Gender extends EnumEntry
case object Gender extends CirceEnum[Gender] with Enum[Gender] {
case object Male extends Gender
case object Female extends Gender
case object Unisex extends Gender
case object Unknown extends Gender
val values = findValues
}
Gender.values.foreach { gender =>
assert(gender.asJson == Json.fromString(gender.entryName))
}
这应该与 circe 的自动推导一起用于您的案例 类。
接受的答案已弃用(大约 0.12.0)。
Circe 现在提供这些功能:
Decoder.decodeEnumeration[E <: Enumeration](enum: E)
Encoder.encodeEnumeration[E <: Enumeration](enum: E)
以例:
implicit val genderDecoder: Decoder[Gender.Value] = Decoder.decodeEnumeration(Gender)
implicit val genderEncoder: Encoder[Gender.Value] = Encoder.encodeEnumeration(Gender)
我正在努力思考 Circe。
所以,这是我得到的模型:
object Gender extends Enumeration {
type Gender = Value
val Male, Female, Unisex, Unknown = Value
}
case class Product(id: String, gender: Gender.Value)
我要
a) 将这个简单示例编码为 JSON 字符串
val product = Product(id = "1234", gender = Gender.Female)
b) 将结果 JSON 映射回产品案例 class.
我自己的尝试并没有让我走得太远:
object JsonProtocol {
implicit val productDecoder: Decoder[Product] = deriveDecoder
implicit val productEncoder: Encoder[Product] = deriveEncoder
}
导致编译时错误
Error:(52, 49) could not find Lazy implicit value of type io.circe.generic.decoding.DerivedDecoder[A]
implicit val productDecoder: Decoder[Product] = deriveDecoder
^
我不知道为什么会抛出这个异常,也不知道解决方案是什么样的。也许是枚举类型的用法?但是,我只是猜测。
尝试使用以下方法为枚举定义您自己的编码器和解码器:
Decoder.enumDecoder[E <: Enumeration](enum: E)
Encoder.enumEncoder[E <: Enumeration](enum: E)
类似于:
object JsonProtocol {
implicit val genderDecoder: Decoder[Gender.Value] = Decoder.enumDecoder(Gender)
implicit val genderEncoder: Encoder[Gender.Value] = Encoder.enumEncoder(Gender)
implicit val productDecoder: Decoder[Product] = deriveDecoder
implicit val productEncoder: Encoder[Product] = deriveEncoder
}
这些是必需的,因为据我所知,automatic/semiautomatic 派生程序仅适用于 sealed trait
和 case classes
的层次结构。您看到该错误的原因是因为 Product
的派生编解码器将隐式要求 encoders/decoders 每个参数的类型。 String
的 encoder/decoder 是 Circe 的标准部分,但您可能需要为自己的枚举创建一个。
如果您想在 circe 中使用枚举,请查看 enumeratum。然后你可以尝试这样的事情:
import enumeratum._
sealed trait Gender extends EnumEntry
case object Gender extends CirceEnum[Gender] with Enum[Gender] {
case object Male extends Gender
case object Female extends Gender
case object Unisex extends Gender
case object Unknown extends Gender
val values = findValues
}
Gender.values.foreach { gender =>
assert(gender.asJson == Json.fromString(gender.entryName))
}
这应该与 circe 的自动推导一起用于您的案例 类。
接受的答案已弃用(大约 0.12.0)。
Circe 现在提供这些功能:
Decoder.decodeEnumeration[E <: Enumeration](enum: E)
Encoder.encodeEnumeration[E <: Enumeration](enum: E)
以例:
implicit val genderDecoder: Decoder[Gender.Value] = Decoder.decodeEnumeration(Gender)
implicit val genderEncoder: Encoder[Gender.Value] = Encoder.encodeEnumeration(Gender)