简体   繁体   English

Circe 和 Scala 的枚举类型

[英]Circe and Scala's Enumeration type

I'm trying to wrap my head around Circe.我正试图绕过Circe。

So, here's the model I've been given:所以,这是我得到的模型:

object Gender extends Enumeration {
     type Gender = Value
     val Male, Female, Unisex, Unknown = Value
}

case class Product(id: String, gender: Gender.Value)

I want to我想要

a) encode this simple example to a JSON string a) 将此简单示例编码为 JSON 字符串

        val product = Product(id = "1234", gender = Gender.Female)

b) map the resulting JSON back onto the Product case class. b) 将生成的 JSON 映射回 Product 案例类。


My own attempt didn't get me very far:我自己的尝试并没有让我走得太远:

  object JsonProtocol {
      implicit val productDecoder: Decoder[Product] = deriveDecoder
      implicit val productEncoder: Encoder[Product] = deriveEncoder
  }

resulted in a compile time error导致编译时错误

   Error:(52, 49) could not find Lazy implicit value of type io.circe.generic.decoding.DerivedDecoder[A]
   implicit val productDecoder: Decoder[Product] = deriveDecoder
                                            ^

I've no idea why this exception is thrown and what the solution could look like.我不知道为什么会抛出这个异常以及解决方案会是什么样子。 Maybe it's the usage of the Enumeration type?也许是枚举类型的用法? But, I'm only guessing.但是,我只是猜测。

Try defining your own encoders and decoders for the enum using:尝试使用以下方法为枚举定义自己的编码器和解码器:

Decoder.enumDecoder[E <: Enumeration](enum: E)
Encoder.enumEncoder[E <: Enumeration](enum: E)

something like:就像是:

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
}

These are needed because the automatic/semiautomatic derivers only work for hierarchies of sealed trait s and case classes as far as I know.这些是必需的,因为据我所知,自动/半自动派生器仅适用于sealed traitcase classes层次结构。 The reason you see that error is because the derived codecs for Product will implicitly require encoders/decoders for the types of each of it's parameters.您看到该错误的原因是Product的派生编解码器将隐式要求编码器/解码器用于其每个参数的类型。 An encoder/decoder for String is a standard part of Circe, but you'll probably need to create ones for your own enumerations. String的编码器/解码器是 Circe 的标准部分,但您可能需要为自己的枚举创建一个。

Have a look at enumeratum if you want to use enumerations with circe.看看enumeratum如果你想使用枚举与瑟茜。 You could then try something like this:然后你可以尝试这样的事情:

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))
}

This should work with circe's automatic derivation for use with your case classes.这应该与 circe 的自动派生一起用于您的案例类。

The accepted answer is deprecated ( circe 0.12.0 ).不推荐使用已接受的答案(大约 0.12.0 )。

Circe provides now these functions: Circe 现在提供以下功能:

Decoder.decodeEnumeration[E <: Enumeration](enum: E)
Encoder.encodeEnumeration[E <: Enumeration](enum: E)

With the example:举个例子:

implicit val genderDecoder: Decoder[Gender.Value] = Decoder.decodeEnumeration(Gender)
implicit val genderEncoder: Encoder[Gender.Value] = Encoder.encodeEnumeration(Gender)

For Scala 3 there is no solution today within Circe .对于Scala 3 ,目前在Circe中没有解决方案。

However there is a library that works nicely: circe-tagged-adt-codec但是有一个运行良好的库: circe-tagged-adt-codec

Here an example that works for me (the rest I do with semiautomatic derivation from Circe):这是一个对我有用的示例(其余部分我使用 Circe 的半自动推导):

enum TestOverrideType derives JsonTaggedAdt.PureEncoder:
  case Exists, NotExists, IsEquals, HasSize

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM