Swift - 如何提取具有相同键名的所有值

问题描述

看了几篇帖子,我没有找到我要找的东西。希望这篇文章能帮到我。

我使用 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,如果这可能有用的话,因为它很容易转换。

要正确解码,请使用 trydo/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\":\"&#36;\",\"rate\":\"56,689.8367\",\"description\":\"United States Dollar\",\"rate_float\":56689.8367},\"GBP\":{\"code\":\"GBP\",\"symbol\":\"&pound;\",\"rate\":\"40,449.3889\",\"description\":\"British Pound Sterling\",\"rate_float\":40449.3889},\"EUR\":{\"code\":\"EUR\",\"symbol\":\"&euro;\",\"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)
}