I am trying to decode this piece of Json:
{
"id" : "e07cff6a-bbf7-4bc9-b2ec-ff2ea8e46288",
"paper" : {
"title" : "Example Title",
"authors" : [
"1bf5e911-8878-4e06-ba8e-8159aadb052c"
]
}
}
However, when it get to the Sets part, its fails. The error message is not helpful.
DecodingFailure([A]Set[A], List())
Here are my docoders:
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)
Here are the case classes used:
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)
Although the error description is far from being explicative, your problem is related to a wrong usage of the monadic API of the decoder: remember that a for comprehension is a syntactic sugar for map/flatMap.
From
io.circe.Decoder
Looking to this code you see that when you flatMap a decoder, you get a new decoder operating on the same cursor: the cursor is the current position of the parsing operation.
In the following code:
The cursor is pointing at the beginning of the object both when you try to decode title and authors. If you do not use semi-automatic or automatic generation and you work natively with the API, you need to move the cursor yourself like so