首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >Circe Scala -编码和解码Map[]和case类

Circe Scala -编码和解码Map[]和case类
EN

Stack Overflow用户
提问于 2018-10-09 01:59:23
回答 2查看 4.7K关注 0票数 3

我正在尝试为我的case类创建一个编码器和解码器:

代码语言:javascript
复制
case class Road(id: String, light: RoadLight, names: Map[String, String])

RoadLight是一个java类,带有枚举。

代码语言:javascript
复制
public enum RoadLight {
red,yellow,green
}

我试着做一个半自动的编码和解码:一个隐式的编码器和解码器。

我已经开始使用MapString,String类型:

代码语言:javascript
复制
implicit val namesDecoder: Decoder[Map[String, String]] = deriveDecoder[Map[String, String]]
implicit val namesEncoder: Encoder[Map[String, String]] = deriveEncoder[Map[String, String]]

但是我确实得到了他们两个的错误!

1:找不到io.circe.generic.decoding.DerivedDecoderA类型的Lazy隐式值

隐式解码: shapeless.Lazy[io.circe.generic.decoding.DerivedDecoderA])io.circe.DecoderA.:2:错误:没有足够的参数用于方法deriveDecoder:未指定的值参数解码。隐式val字符串:解码器[MapString,namesDecoder]= deriveDecoder

我已经照章办事了,不明白出了什么问题。我甚至没有尝试解析case类,而只是解析map,即使这样也不能工作。

有什么想法吗?谢谢!

EN

回答 2

Stack Overflow用户

发布于 2018-10-09 02:06:48

Scaladoc说

代码语言:javascript
复制
/**
 * Semi-automatic codec derivation.
 *
 * This object provides helpers for creating [[io.circe.Decoder]] and [[io.circe.ObjectEncoder]]
 * instances for case classes, "incomplete" case classes, sealed trait hierarchies, etc.

Map不是密封特征层次结构的case类或元素。

https://github.com/circe/circe/issues/216

Encode Map[String, MyCaseClass] into Seq[String, String] using circe

Circe and Scala's Enumeration type

票数 4
EN

Stack Overflow用户

发布于 2018-10-09 07:45:46

circe-generic不为java枚举创建编解码器,只为scala product和sum类型创建编解码器。但是,为RoadLight开发自己的应用程序并不难。一旦你有了它,你就会得到地图。

下面的代码可以工作:

代码语言:javascript
复制
object RoadLightCodecs {
  implicit val decRl: Decoder[RoadLight] = Decoder.decodeString.emap {
    case "red" => Right(RoadLight.Red)
    case "yellow" => Right(RoadLight.Yellow)
    case "green" => Right(RoadLight.Green)
    case s => Left(s"Unrecognised traffic light $s")
  }

  implicit val encRl: Encoder[RoadLight] = Encoder.encodeString.contramap(_.toString)


  implicit val decodeMap = Decoder.decodeMap[String, RoadLight]
  implicit val encodeMap = Encoder.encodeMap[String, RoadLight]
}

因此,我们所做的是为基本类型制作编解码器,然后使用它们来构建更大的map编解码器。

据我所知,目前还没有为java枚举自动执行此操作的库,尽管理论上应该可以编写一个。但是在基本的编解码器上使用组合子来构建更复杂的编解码器,效果很好,扩展性也很好。

编辑:我曾经尝试过自动派生java enum编解码器,你几乎可以做到:

代码语言:javascript
复制
  def decodeEnum[E <: Enum[E]](values: Array[E]): Decoder[E] = Decoder.decodeString.emap { str =>
    values.find(_.toString.toLowerCase == str)
      .fold[Either[String, E]](Left(s"Value $str does not map correctly"))(Right(_))
  }

  def encodeEnum[E <: Enum[E]]: Encoder[E] =
    Encoder.encodeString.contramap(_.toString.toLowerCase)

  implicit val roadLightDecoder = decodeEnum[RoadLight](RoadLight.values())
  implicit val roadLightEncoder = encodeEnum[RoadLight]

因此,encodeEnum可以是自动的(您可以将其设为隐式,而不是末尾的val ),但是解码器需要给定值(我认为无法从类型中自动获取),因此您需要在创建编解码器时传递这些值。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52707765

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档