Reputation: 11275
Let's use this example JSON:
{
"bids": [
[16182.06, 0.02994158],
[16179.56, 0.01902097],
[16178.05, 0.06538498]
],
"asks": [
[16191.92, 0.03597287],
[16193.33, 0.0839688],
[16194.95, 0.0857127]
]
}
Nothing special, in fact, this could be simply parsed to a case class:
@JsonCodec case class OrderBook(bids: Seq[Seq[Double]], asks: Seq[Seq[Double]])
This works great...
I actually know that every array will be of size 2, and
I want to fix this with Circe
and parse it to a class structure like:
@JsonCodec case class OrderBook(bids: Seq[Elems], asks: Seq[Elems])
case class Elems(rate: Double, amount: Double)
I have tried writing my Encoder and Decoder:
object Elems {
implicit val encodeElems: Encoder[Elems] = (a: Elems) =>
Json.arr(
Json.fromDoubleOrNull(a.rate), Json.fromDoubleOrNull(a.amount)
)
implicit val decodeElems: Decoder[Elems] = (c: HCursor) =>
for {
f <- c.downArray.as[Seq[Double]]
} yield {
Elems(f(0), f(1))
}
}
But it always fails on me with an error:
Caused by: DecodingFailure(CanBuildFrom for A, List(DownArray, DownArray, DownField(bids)))
Why? What am I doing wrong?
Upvotes: 2
Views: 1414
Reputation: 29193
downArray
moves the focus from a list to its first element. When Elems.decodeElems
is used, c = <[1, 2]>
, so c.downArray = <1>
, and then you try <1>.as[Seq[Double]]
, which explodes. Second, you should use as[(Double, Double)]
, which will decode a list like you do, but will also make sure it is exactly 2 elements long.
implicit val decodeElems: Decoder[Elems] = (c: HCursor) =>
for {
f <- c.as[(Double, Double)]
} yield Elems(f._1, f._2)
Upvotes: 5