无法解码 Circe 中的集合
Cannot decode Sets in Circe
我正在尝试解码这段 Json:
{
"id" : "e07cff6a-bbf7-4bc9-b2ec-ff2ea8e46288",
"paper" : {
"title" : "Example Title",
"authors" : [
"1bf5e911-8878-4e06-ba8e-8159aadb052c"
]
}
}
但是,当它到达集合部分时,它失败了。错误消息没有帮助。
DecodingFailure([A]Set[A], List())
这是我的编码器:
implicit val paperIdDecoder: Decoder[PaperId] = Decoder.decodeString.emap[PaperId] { str ⇒
Either.catchNonFatal(PaperId(str)).leftMap(_.getMessage)
}
implicit val paperAuthorDecoder: Decoder[PaperAuthor] = Decoder.decodeString.emap[PaperAuthor] { str ⇒
Either.catchNonFatal(PaperAuthor(str)).leftMap(_.getMessage)
}
implicit val paperDecoder: Decoder[Paper] = {
for {
title <- Decoder.decodeString
authors <- Decoder.decodeSet[PaperAuthor]
} yield Paper(title, authors)
}
implicit val paperViewDecoder: Decoder[PublishedPaperView] = for {
id <- Decoder[PaperId]
paper <- Decoder[Paper]
} yield PublishedPaperView(id, paper)
这里是 类 使用的案例:
case class PublishedPaperView(id: PaperId, paper: Paper)
case class PaperId(value: String)
case class Paper(title: String, authors: Set[PaperAuthor])
case class PaperAuthor(value: String)
尽管错误描述远非解释性的,但您的问题与解码器monadic API 的错误使用有关:请记住,理解是 map/flatMap.
的 语法糖
来自io.circe.Decoder
/**
* Monadically bind a function over this [[Decoder]].
*/
final def flatMap[B](f: A => Decoder[B]): Decoder[B] = new Decoder[B] {
final def apply(c: HCursor): Decoder.Result[B] = self(c).flatMap(a => f(a)(c))
override def tryDecode(c: ACursor): Decoder.Result[B] = {
self.tryDecode(c).flatMap(a => f(a).tryDecode(c))
}
override def decodeAccumulating(c: HCursor): AccumulatingDecoder.Result[B] =
self.decodeAccumulating(c).andThen(result => f(result).decodeAccumulating(c))
}
查看这段代码,您会发现当您对解码器进行 flatMap 时,您会得到一个在同一 cursor 上运行的新解码器:光标是解析操作的当前位置。
在下面的代码中:
implicit val paperDecoder: Decoder[Paper] = {
for {
title <- Decoder.decodeString
authors <- Decoder.decodeSet[PaperAuthor]
} yield Paper(title, authors)
}
当您尝试解码标题和作者时,光标指向 object 的开头。 如果您不使用 semi-automatic 或自动生成并且您使用 API 本机工作,您需要像这样自己移动光标
implicit val paperDecoder: Decoder[Paper] = Decoder.instance(cursor => Xor.right(Paper("",Set.empty)))
implicit val paperViewDecoder: Decoder[PublishedPaperView] = Decoder.instance(
cursor =>
for {
id <- cursor.downField("id").as[PaperId]
paper <- cursor.downField("paper").as[Paper]
} yield PublishedPaperView(id, paper)
)
我正在尝试解码这段 Json:
{
"id" : "e07cff6a-bbf7-4bc9-b2ec-ff2ea8e46288",
"paper" : {
"title" : "Example Title",
"authors" : [
"1bf5e911-8878-4e06-ba8e-8159aadb052c"
]
}
}
但是,当它到达集合部分时,它失败了。错误消息没有帮助。
DecodingFailure([A]Set[A], List())
这是我的编码器:
implicit val paperIdDecoder: Decoder[PaperId] = Decoder.decodeString.emap[PaperId] { str ⇒
Either.catchNonFatal(PaperId(str)).leftMap(_.getMessage)
}
implicit val paperAuthorDecoder: Decoder[PaperAuthor] = Decoder.decodeString.emap[PaperAuthor] { str ⇒
Either.catchNonFatal(PaperAuthor(str)).leftMap(_.getMessage)
}
implicit val paperDecoder: Decoder[Paper] = {
for {
title <- Decoder.decodeString
authors <- Decoder.decodeSet[PaperAuthor]
} yield Paper(title, authors)
}
implicit val paperViewDecoder: Decoder[PublishedPaperView] = for {
id <- Decoder[PaperId]
paper <- Decoder[Paper]
} yield PublishedPaperView(id, paper)
这里是 类 使用的案例:
case class PublishedPaperView(id: PaperId, paper: Paper)
case class PaperId(value: String)
case class Paper(title: String, authors: Set[PaperAuthor])
case class PaperAuthor(value: String)
尽管错误描述远非解释性的,但您的问题与解码器monadic API 的错误使用有关:请记住,理解是 map/flatMap.
的 语法糖来自io.circe.Decoder
/**
* Monadically bind a function over this [[Decoder]].
*/
final def flatMap[B](f: A => Decoder[B]): Decoder[B] = new Decoder[B] {
final def apply(c: HCursor): Decoder.Result[B] = self(c).flatMap(a => f(a)(c))
override def tryDecode(c: ACursor): Decoder.Result[B] = {
self.tryDecode(c).flatMap(a => f(a).tryDecode(c))
}
override def decodeAccumulating(c: HCursor): AccumulatingDecoder.Result[B] =
self.decodeAccumulating(c).andThen(result => f(result).decodeAccumulating(c))
}
查看这段代码,您会发现当您对解码器进行 flatMap 时,您会得到一个在同一 cursor 上运行的新解码器:光标是解析操作的当前位置。
在下面的代码中:
implicit val paperDecoder: Decoder[Paper] = {
for {
title <- Decoder.decodeString
authors <- Decoder.decodeSet[PaperAuthor]
} yield Paper(title, authors)
}
当您尝试解码标题和作者时,光标指向 object 的开头。 如果您不使用 semi-automatic 或自动生成并且您使用 API 本机工作,您需要像这样自己移动光标
implicit val paperDecoder: Decoder[Paper] = Decoder.instance(cursor => Xor.right(Paper("",Set.empty)))
implicit val paperViewDecoder: Decoder[PublishedPaperView] = Decoder.instance(
cursor =>
for {
id <- cursor.downField("id").as[PaperId]
paper <- cursor.downField("paper").as[Paper]
} yield PublishedPaperView(id, paper)
)