【问题标题】:Scala: How to decode a List of objects with CirceScala:如何使用 Circe 解码对象列表
【发布时间】:2021-11-11 19:13:26
【问题描述】:

我的GreedIndex 解码器无法正常工作,但我似乎无法弄清楚原因;我认为这真的很愚蠢。

我认为这可能是 timeStampList[CryptoData] 的问题

case class CryptoData(greedValue: String, valueClassification: Sentiment, timeStamp: Long)

case class GreedIndex(name: String, data: List[CryptoData])

object GreedIndex {
  implicit val greedDecoder: Decoder[GreedIndex] = Decoder.instance { json =>

    for {
      name <- json.get[String]("name")
      data <- json.get[List[CryptoData]]("data")
    } yield GreedIndex(name, data)
  }
}

object CryptoData {

  implicit val cryptoDecoder: Decoder[CryptoData] = Decoder.instance { json =>
    val data = json.downField("data").downArray
    for {
      value               <- data.get[String]("value")
      valueClassification <- data.get[Sentiment]("value_classification")
      timestamp           <- data.get[String]("timestamp")
    } yield CryptoData(value, valueClassification, timestamp.toLong * 1000)
  }

}

我正在尝试解码的 JSON 对象。

{
  "name" : "Fear and Greed Index",
  "data" : [
    {
      "value" : "53",
      "value_classification" : "Neutral",
      "timestamp" : "1631750400",
      "time_until_update" : "17264"
    },
    {
      "value" : "49",
      "value_classification" : "Neutral",
      "timestamp" : "1631664000"
    },
    {
      "value" : "30",
      "value_classification" : "Fear",
      "timestamp" : "1631577600"
    }
  ],
  "metadata" : {
    "error" : null
  }
}

【问题讨论】:

  • 为什么不直接使用这些解码器的半自动派生?
  • 感谢您的回复。我确实尝试过,但无法让它工作。不过,理想情况下,我会尝试更深入地了解自定义编解码器。
  • 你不需要去CryptoData解码器中的data数组,这是List[x]解码器的工作。 scastie.scala-lang.org/BalmungSan/BvCAq4OFRqyf8jKH2hzFjw/4
  • 我不确定这是否正确,因为我已经尝试了 CryptoData 解码器本身,并且当数据数组中只有一个对象时它可以工作
  • 你有Sentiment解码器吗?它不起作用是什么意思?它无法编译或者您有运行时问题?如果是后者,则打印解码问题。

标签: scala circe


【解决方案1】:

这是怎么做的:

import io.circe._
import io.circe.generic.extras.semiauto.deriveEnumerationDecoder
import io.circe.generic.semiauto.deriveDecoder

case class CryptoData(
    greedValue: String,
    valueClassification: Sentiment,
    timeStamp: Long
)

object CryptoData {
  implicit val decoder = Decoder.forProduct3(
    "value",
    "value_classification",
    "timestamp"
  )(CryptoData.apply)
}

sealed trait Sentiment
object Sentiment {
  object Neutral extends Sentiment
  object Fear extends Sentiment

  implicit val decoder: Decoder[Sentiment] = deriveEnumerationDecoder
}

case class GreedIndex(name: String, data: List[CryptoData])

object GreedIndex {
  implicit val greedDecoder: Decoder[GreedIndex] = deriveDecoder
}

GreedIndex 的字段名称与 JSON 中的字段名称匹配,因此在这种情况下您可以使用 deriveDecoder。对于CryptoData则不是这样,所以需要用forProduct3手动编写。

由于您尚未定义Sentiment,因此我将其建模为枚举。如果要为此使用deriveDecoder,则必须在 JSON 中像这样对其建模:{"Neutral": {}}。要使用简单的字符串格式,您需要改用 circe-generic-extras 模块中的 deriveEnumerationDecoder

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-07-06
    • 2022-01-13
    • 1970-01-01
    • 2020-07-06
    • 2017-10-03
    • 2019-05-31
    • 2020-05-31
    • 2020-05-29
    相关资源
    最近更新 更多