我正在尝试为我的case类创建一个编码器和解码器:
case class Road(id: String, light: RoadLight, names: Map[String, String])
RoadLight是一个java类,带有枚举。
public enum RoadLight {
red,yellow,green
}
我试着做一个半自动的编码和解码:一个隐式的编码器和解码器。
我已经开始使用MapString,String类型:
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,即使这样也不能工作。
有什么想法吗?谢谢!
发布于 2018-10-09 02:06:48
Scaladoc说
/**
* 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
发布于 2018-10-09 07:45:46
circe-generic
不为java枚举创建编解码器,只为scala product和sum类型创建编解码器。但是,为RoadLight
开发自己的应用程序并不难。一旦你有了它,你就会得到地图。
下面的代码可以工作:
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编解码器,你几乎可以做到:
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 ),但是解码器需要给定值(我认为无法从类型中自动获取),因此您需要在创建编解码器时传递这些值。
https://stackoverflow.com/questions/52707765
复制相似问题