【问题标题】:Parse JSON array as case class with Circe使用 Circe 将 JSON 数组解析为案例类
【发布时间】:2017-09-09 15:48:01
【问题描述】:

让我们使用这个 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]
  ]
}

没什么特别的,其实这可以简单的解析成一个case类:

@JsonCodec case class OrderBook(bids: Seq[Seq[Double]], asks: Seq[Seq[Double]])

这很好用...


问题

我实际上知道每个数组的大小都是 2,并且

  • 第一个元素 -> 它是“率”
  • 第二个元素 -> 它是“金额”

我想用Circe 解决这个问题并将其解析为一个类结构,例如:

@JsonCodec case class OrderBook(bids: Seq[Elems], asks: Seq[Elems])

case class Elems(rate: Double, amount: Double)

我已经尝试编写我的编码器和解码器:

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))
    }
}

但它总是因错误而失败:

Caused by: DecodingFailure(CanBuildFrom for A, List(DownArray, DownArray, DownField(bids)))

为什么?我做错了什么?

【问题讨论】:

    标签: json scala circe


    【解决方案1】:

    downArray 将焦点从列表移动到其第一个元素。当Elems.decodeElems被使用时,c = &lt;[1, 2]&gt;,所以c.downArray = &lt;1&gt;,然后你尝试&lt;1&gt;.as[Seq[Double]],它会爆炸。其次,您应该使用as[(Double, Double)],它会像您一样对列表进行解码,但也会确保它的长度正好是 2 个元素。

    implicit val decodeElems: Decoder[Elems] = (c: HCursor) =>
      for {
        f <- c.as[(Double, Double)]
      } yield Elems(f._1, f._2)
    

    【讨论】:

      猜你喜欢
      • 2017-04-12
      • 1970-01-01
      • 2021-09-10
      • 2019-03-15
      • 1970-01-01
      • 2019-11-02
      • 2016-09-21
      • 2014-06-25
      • 2021-06-09
      相关资源
      最近更新 更多