swift 将json结果转换为动态

enxuqcxy  于 2022-12-10  发布在  Swift
关注(0)|答案(1)|浏览(130)

对于初学者来说,我有一个非常复杂的问题。首先,我从json得到了这个结果

{
  "success": true,
  "timeframe": true,
  "start_date": "2018-01-01",
  "end_date": "2018-01-05",
  "source": "TRY",
  "quotes": {
    "2018-01-01": {
      "TRYEUR": 0.21947
    },
    "2018-01-02": {
      "TRYEUR": 0.220076
    },
    "2018-01-03": {
      "TRYEUR": 0.220132
    },
    "2018-01-04": {
      "TRYEUR": 0.220902
    },
    "2018-01-05": {
      "TRYEUR": 0.222535
    }
  }
}

当我使用https://app.quicktype.io创建对象时,它给出了这个,这是正确的。

import Foundation

// MARK: - APIResult
struct APIResult {
    let success, timeframe: Bool
    let startDate, endDate, source: String
    let quotes: [String: Quote]
}

// MARK: - Quote
struct Quote {
    let tryeur: Double
}

但我不希望我的货币像这样硬编码,所以如果我选择:USD to:EUR在我的应用程序中,我希望在Quote下得到结果为USDEUR。我还知道,如果我在此结构中更改任何内容,它将不起作用。那么,将如何使这些货币选择动态化,以使其在不同的货币中工作。这是一个货币转换器应用程序,我希望得到这些汇率,并在我的应用程序中的图表上反映出来。谢谢

vyu0f0g1

vyu0f0g11#

Decodable用途广泛,可高度定制。
编写一个自定义的初始化器,并将引号字典Map到一个包含日期和引号的Quote示例数组。键TRYEUR是无关的,将被忽略。

let jsonString = """
{
  "success": true,
  "timeframe": true,
  "start_date": "2018-01-01",
  "end_date": "2018-01-05",
  "source": "TRY",
  "quotes": {
    "2018-01-01": {
      "TRYEUR": 0.21947
    },
    "2018-01-02": {
      "TRYEUR": 0.220076
    },
    "2018-01-03": {
      "TRYEUR": 0.220132
    },
    "2018-01-04": {
      "TRYEUR": 0.220902
    },
    "2018-01-05": {
      "TRYEUR": 0.222535
    }
  }
}
"""

struct APIResult: Decodable {
    private enum CodingKeys: String, CodingKey {
        case success, timeframe, startDate = "start_date", endDate = "end_date", source, quotes
    }
    let success, timeframe: Bool
    let startDate, endDate, source: String
    let quotes: [Quote]
    
    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        success = try container.decode(Bool.self, forKey: .success)
        timeframe = try container.decode(Bool.self, forKey: .timeframe)
        startDate = try container.decode(String.self, forKey: .startDate)
        endDate = try container.decode(String.self, forKey: .endDate)
        source =  try container.decode(String.self, forKey: .source)
        let quoteData = try container.decode([String: [String:Double]].self, forKey: .quotes)
        quotes = quoteData.compactMap({ (key, value) in
            guard let quote = value.values.first else { return nil }
            return Quote(date: key, quote: quote)
        }).sorted{$0.date < $1.date}
    }
}

struct Quote {
    let date: String
    let quote: Double
}

do {
    let result = try  JSONDecoder().decode(APIResult.self, from: Data(jsonString.utf8))
    print(result)
} catch {
    print(error)
}

相关问题