问题描述
看了几篇帖子,我没有找到我要找的东西。希望这篇文章能帮到我。
我使用 CoinDesk 的 api,我现在要做的是在答案中检索所有代码(欧元、美元、英镑),但我无法获得所有资产。
{-# OPTIONS_GHC -Wall #-}
module Operators where
import Text.Megaparsec
import Text.Megaparsec.Char
import Control.Monad.Combinators.Expr
import Data.Void
type Parser = Parsec Void String
data Expr
= Access Expr String
| ArrayIndex Expr Expr
| Var String
| Lit Int
deriving (Show)
expr :: Parser Expr
expr = makeExprParser term opTable
identifier :: Parser String
identifier = some letterChar
term :: Parser Expr
term = Var <$> identifier
<|> Lit . read <$> some digitChar
opTable :: [[Operator Parser Expr]]
opTable = [[ indexAccessChain ]]
indexAccessChain :: Operator Parser Expr
indexAccessChain = Postfix $ foldr1 (flip (.)) <$> some (singleIndex <|> singleAccess)
singleIndex,singleAccess :: Parser (Expr -> Expr)
singleIndex = flip ArrayIndex <$> brackets expr
singleAccess = flip Access <$> (char '.' *> identifier)
brackets :: Parser a -> Parser a
brackets = between (char '[') (char ']')
main :: IO ()
main = parseTest expr "s.a[1][2][3].b.c[4][5][6]"
这里是我将如何获取数据
公共类网络管理器{
SliverAnimatedSwitcher(
duration: kThemeAnimationDuration,child: content,)
}
我想在 bpi 密钥中获取所有代码并将它们放在一个列表中以使用它们。
解决方法
在我看来,这里处理 json 的最好方法是将“bpi”下的内容视为字典。
struct CoinData: Codable {
let time: Time
let chartName: String
let bpi: [String: BPI]
}
struct BPI: Codable {
let code: String
let rate: Double
enum CodingKeys: String,CodingKey {
case code
case rate = "rate_float"
}
}
struct Time: Codable {
let updated: Date
enum CodingKeys: String,CodingKey {
case updated = "updatedISO"
}
}
我删除了一些不必要的 (?) 属性,并注意到我将 updatedISO
中的 Time
变成了 Date
,如果这可能有用的话,因为它很容易转换。
要正确解码,请使用 try
和 do/catch
,以便正确处理错误。
这里有一个例子,我还遍历了不同的货币/利率
do {
let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .iso8601
let result = try decoder.decode(CoinData.self,from: data)
print(result.time.updated)
let coins = result.bpi.values
for coin in coins {
print(coin)
}
} catch {
print(error)
}
输出:
2021-02-20 19:48:00 +0000
BPI(代码:“GBP”,汇率:40681.1111)
BPI(代码:“美元”,汇率:57014.5954)
BPI(代码:“EUR”,汇率:47048.5582)
您应该使用对象来表示来自服务器的数据。应该是这样的:
struct CoinData: Codable {
let time: Time
let disclaimer,chartName: String
let bpi: BPI
}
struct BPI: Codable {
let usd,gbp,eur: Eur
enum CodingKeys: String,CodingKey {
case usd = "USD"
case gbp = "GBP"
case eur = "EUR"
}
}
struct Eur: Codable {
let code,symbol,rate,eurDescription: String
let rateFloat: Double
enum CodingKeys: String,CodingKey {
case code,rate
case eurDescription = "description"
case rateFloat = "rate_float"
}
}
struct Time: Codable {
let updated: String
let updatedISO: String
let updateduk: String
}
当你下载数据时,你会像这样解析它:
let coinData = try? JSONDecoder().decode(CoinData.self,from: jsonData)
coinData?.bpi.eur // Access EUR for instance
更新:
使用从服务器获取的数据来演示解析的简单演示:
let dataFromServer = "{\"time\":{\"updated\":\"Feb 20,2021 21:02:00 UTC\",\"updatedISO\":\"2021-02-20T21:02:00+00:00\",\"updateduk\":\"Feb 20,2021 at 21:02 GMT\"},\"disclaimer\":\"This data was produced from the CoinDesk Bitcoin Price Index (USD). Non-USD currency data converted using hourly conversion rate from openexchangerates.org\",\"chartName\":\"Bitcoin\",\"bpi\":{\"USD\":{\"code\":\"USD\",\"symbol\":\"$\",\"rate\":\"56,689.8367\",\"description\":\"United States Dollar\",\"rate_float\":56689.8367},\"GBP\":{\"code\":\"GBP\",\"symbol\":\"£\",\"rate\":\"40,449.3889\",\"description\":\"British Pound Sterling\",\"rate_float\":40449.3889},\"EUR\":{\"code\":\"EUR\",\"symbol\":\"€\",\"rate\":\"46,780.5666\",\"description\":\"Euro\",\"rate_float\":46780.5666}}}"
do {
let json = try JSONDecoder().decode(CoinData.self,from: dataFromServer.data(using: .utf8)!)
print(json.bpi.eur) // Will print EUR object
} catch let error {
print(error)
}