1

嗨,如果 JSON 具有键和值,并且您可以使用键名来提取其值,那么文档中的 Decode Person 示例非常好,但是如果构成键的字符串是任意但有意义的呢?

对于 Fxample,一个开放的加密货币 api 可以给出硬币的历史价格,并且返回的 JSON 的结构会有所不同,具体取决于我要求的硬币的基础货币和我希望它定价的各种报价货币。例如,让我们说我想要“AUD”和“XRP”中“DOGE”特定日期的价格,返回的 JSON 看起来像

{"DOGE":{"AUD":0.008835,"XRP":0.004988}}

我无法导航到基础并获取其价值,然后价格并获取它们,因为 JSON 不是以这种方式构建的,我需要查找“DOGE”作为键,然后在重新生成的对象中知道会有一个“AUD” '键和'XRP'键。当然,根据我的查询,每个结果都会有所不同。

当然,当我基于它们创建搜索时,我知道这些键,但是我如何使用 Argonaut 来解析这个 JSON?我可以以某种方式创建一个关闭我的键名的解码吗?

感谢任何帮助或指导,谢谢。

4

2 回答 2

1

由于您不提前知道属性名称是什么,因此您无法创建编解码器并将原始 JSON 直接解码为 Scala 类。

您想将原始 JSON 解析为通用argonaut.Json对象,然后您可以进行模式匹配或用于fold检查内容。例如:

val rawJson: String = ...
val parsed: Either[String, argonaut.Json] = argonaut.Parse.parse(rawJson)

Json您可以通过检查源代码来查看 argonaut 对象上可用的方法。

于 2018-02-05T05:19:40.727 回答
1

根据 Fried Brice 的回答,我确实沿着解析路径进行了映射,然后映射了生成的 Either 以生成我的数据类型,请参见下面的代码片段,欢迎提出建议和改进。

def parseHistoricPriceJSON(rawJson: String, fromcurrency: Currency, toCurrencies: List[Currency]): Either[String, PricedAsset] = {
import argonaut._, Argonaut._
import monocle.macros.syntax.lens._
val parsed: Either[String, Json] = Parse.parse(rawJson)
val myTocurrs = Currency("XRP") :: toCurrencies

parsed.right.map(outer => {
  val cursor = outer.cursor
  val ps = for {
    toC <- myTocurrs
    prices <- cursor.downField(fromcurrency.sym)
    price <- prices.downField(toC.sym)
    thep <- price.focus.number
  } yield (toC, thep.toDouble.get)

  PricedAsset(fromcurrency, ps)
})

}

case class Currency(sym: String) extends AnyVal {
  def show = sym
}

case class PricedAsset(base:Currency, quotePrices: List[(Currency,Double)])
于 2018-03-13T03:14:04.417 回答