【问题标题】:How to parse one block of JSON data instead of the entire JSON sequence如何解析一个 JSON 数据块而不是整个 JSON 序列
【发布时间】:2019-06-19 14:07:24
【问题描述】:

以下是用于解析 JSON api 的代码。该代码有效,我能够将所有 JSON 值解析到下面的结构中,但我想知道如何仅解析第一个块(?)/数组并将它们存储在结构中,以便我可以对它们执行操作。

     let jsonUrlString = "https://www.alphavantage.co/query?function=FX_INTRADAY&from_symbol=EUR&to_symbol=USD&interval=5min&apikey=demo"

        let urlObj = URL(string: jsonUrlString)

        URLSession.shared.dataTask(with: urlObj!) {(data, response, error) in
            guard let data = data else { return }
            do {
                let forex = try JSONDecoder().decode(Root.self, from: data)
                print(forex.timeSeriesFX5Min)
            } catch {

                print(error)
            }

            }.resume()
    }
}

struct Root: Codable {
    let timeSeriesFX5Min: [String:Forex]

    enum CodingKeys: String, CodingKey {
        case timeSeriesFX5Min = "Time Series FX (5min)"
    }
}


    // MARK: - TimeSeriesFX5Min
    struct Forex: Codable {
        let the1Open, the2High, the3Low, the4Close: String

        enum CodingKeys: String, CodingKey {
            case the1Open = "1. open"
            case the2High = "2. high"
            case the3Low = "3. low"
            case the4Close = "4. close"
        }

    }

【问题讨论】:

  • first block 是什么意思?
  • 当你通过 url 打开 JSON api 时,你会得到一个值列表: "Time Series FX (5min)": { "2019-06-19 14:35:00": { "1 . open": "1.1213", "2. high": "1.1213", "3. low": "1.1210", "4. close": "1.1212" },我试图捕获第一组值而不是所有这些,然后存储第一个值块,以便它们可以用于执行操作。

标签: json swift decodable


【解决方案1】:

我看到了两种方法,第一种需要更改根结构,我们需要在其中使用消息的元数据部分

struct Root: Codable {
    let metaData: [String: String]
    let timeSeriesFX5Min: [String:Forex]

    enum CodingKeys: String, CodingKey {
        case timeSeriesFX5Min = "Time Series FX (5min)"
        case metaData = "Meta Data"
    }
}

然后我们拿起标有“Last Refresed”的项目,并使用该值在时间序列字典中查找最新的价格条目

do {
    let forex = try JSONDecoder().decode(Root.self, from: data)
    print(forex.metaData)
    if let latestTime = forex.metaData["4. Last Refreshed"], let latestForex = forex.timeSeriesFX5Min[latestTime] {
        print(latestForex)
    }        
} catch {
    print(error)
}

另一种选择是利用时间戳以可以正确排序的格式给出的事实,因此我们不使用元数据对键进行排序并选择最后一项

if let latestTime = forex.timeSeriesFX5Min.keys.sorted().last, let latestForex = forex.timeSeriesFX5Min[latestTime] {
     print(latestForex)
}

【讨论】:

  • 您能解释一下解决方案一背后的原因吗?它奏效了,谢谢你,但我想了解你为什么选择这种方法用于未来的目的。
  • 首先我并没有选择其中一个,我只是碰巧按顺序呈现它们。第一个解决方案的优点是它为最后一条记录提供了清晰的参考,但需要更多的代码并且依赖于元数据结构不会改变。第二个更简单,但如果相关的话,由于排序可能会慢一点。
【解决方案2】:

当您发出请求时,您可能会通过回调通知谁使用请求值调用您的方法,对吧? 因此,您将创建对象或数组对象的新实例并填充结果。

如果您要在此结构中创建,您只需使用您的 arrayObject 并使用 .first 并按照此执行您的逻辑...

例子:

var newRoot: [Root] = [] 
func loadRoot() {
    Service().makeRequest() { (result, error) int
         newRoot = result.results
         print(newRoot.first)
    }
}

函数“makeRequest()”会调用你写的方法。

let jsonUrlString = "https://www.alphavantage.co/query?function=FX_INTRADAY&from_symbol=EUR&to_symbol=USD&interval=5min&apikey=demo"

    let urlObj = URL(string: jsonUrlString)

    URLSession.shared.dataTask(with: urlObj!) {(data, response, error) in
        guard let data = data else { return }
        do {
            let forex = try JSONDecoder().decode(Root.self, from: data)
            print(forex.timeSeriesFX5Min)
        } catch {

            print(error)
        }

        }.resume()
}
}

【讨论】:

  • 这个函数只会解析第一个值块,然后将它们存储在创建的结构中?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-10-17
  • 1970-01-01
  • 2022-12-02
  • 1970-01-01
相关资源
最近更新 更多