首页 > 解决方案 > 如何解码对象中数组中的嵌套 JSON 对象?

问题描述

我需要在嵌套的 JSON 中检索数据,但这样做时遇到了很多麻烦。有问题的文件可以在https://waterservices.usgs.gov/nwis/iv/?format=json&indent=on&sites=08155200¶meterCd=00065&siteStatus=all找到。

// MARK: - Post
struct Post: Codable {
    let name, declaredType, scope: String?
    let value: PostValue?
    let postNil, globalScope, typeSubstituted: Bool?

    enum CodingKeys: String, CodingKey {
        case name, declaredType, scope, value
        case postNil
        case globalScope, typeSubstituted
    }
}

// MARK: - PostValue
struct PostValue: Codable {
    let queryInfo: QueryInfo?
    let timeSeries: [TimeSery]?
}

// MARK: - QueryInfo
struct QueryInfo: Codable {
    let queryURL: String?
    let criteria: Criteria?
    let note: [Note]?
}

// MARK: - Criteria
struct Criteria: Codable {
    let locationParam, variableParam: String?
    let parameter: [JSONAny]?
}

// MARK: - Note
struct Note: Codable {
    let value, title: String?
}

// MARK: - TimeSery
struct TimeSery: Codable {
    let sourceInfo: SourceInfo?
//    let variable: Variable?
//    let values: [TimeSeryValue]?
    let name: String?
}

// MARK: - SourceInfo
struct SourceInfo: Codable {
    let siteName: String?
//    let siteCode: [SiteCode]?
//    let timeZoneInfo: TimeZoneInfo?
    let geoLocation: GeoLocation?
    let note, siteType: [JSONAny]?
//    let siteProperty: [SiteProperty]?
}

// MARK: - GeoLocation
struct GeoLocation: Codable {
    let geogLocation: GeogLocation?
    let localSiteXY: [JSONAny]?
}

// MARK: - GeogLocation
struct GeogLocation: Codable {
    let srs: String?
    let latitude, longitude: Double?
}

检索数据的代码:

URLSession.shared.dataTask(with: url) { data, _, _ in
    if let data = data {
        let posts = try! JSONDecoder().decode(Post.self, from: data)
        if let coord = (posts.value?.timeSeries?.sourceInfo?.geoLocation?.geogLocation?.srs) {
            print(coord)
        }
    }
}.resume()

不幸的是,这会返回错误

error: ParseJSON.playground:330:89: error: type of expression is ambiguous without more context

标签: iosjsonswift

解决方案


timeSeries定义为[TimeSery],表示它是一个数组,但您试图访问它,就好像它只是一个值一样。由于我不确定您的意图是什么,因此很难说确切的解决方法是什么,但一种可能性是first从中访问值(相当于要求 for [0],但它返回一个 Optional):

posts.value?.timeSeries?.first?.sourceInfo?.geoLocation?.geogLocation?.srs

顺便说一句,调试此问题的一种方法是将表达式分解为不太复杂的部分(我开始只是posts.value添加代码,直到您找到问题(在这种情况下,timeSeries.sourceInfo


推荐阅读