Swift JSONDecoder错误-预期对Dictionary <String,Any>进行解码,但找到一个数组

问题描述

我是Swift 5.3的新手,无法检索嵌套的JSON数据。 我的JSON数据结果如下:

 {
    "sites":[
       {
          "site_no":"16103000","station_nm":"Hanalei River nr Hanalei,Kauai,HI","dec_lat_va":22.1796,"dec_long_va":-159.466,"huc_cd":"20070000","tz_cd":"HST","flow":92.8,"flow_unit":"cfs","flow_dt":"2020-08-18 07:10:00","stage":1.47,"stage_unit":"ft","stage_dt":"2020-08-18 07:10:00","class":0,"percentile":31.9,"percent_median":"86.73","percent_mean":"50.77","url":"https:\/\/waterdata.usgs.gov\/hi\/nwis\/uv?site_no=16103000"
       }
    ]
 }

我的结构如下:

struct APIResponse: Codable {
    let sites: APIResponseSites
}

struct APIResponseSites: Codable {
    let station_nm: String
    let stage: Float
}

我的解码SWIFT如下所示:

    let task = URLSession.shared.dataTask(with: url,completionHandler: {
        data,_,error in
        guard let data = data,error == nil else {
            return
        }
        
        var result: APIResponse?
        do {
            result = try JSONDecoder().decode(APIResponse.self,from: data)
        }
        catch {
            print("Failed to decode with error: \(error)")
        }
        
        guard let final = result else {
            return
        }
        
        print(final.sites.station_nm)
        print(final.sites.stage)
        

    })

当然,我收到一条错误消息,指出:

无法解码,并显示以下错误: typeMismatch(Swift.Dictionary , Swift.DecodingError.Context(codingPath:[CodingKeys(stringValue: “ sites”,intValue:nil)],debugDescription:“预期解码 Dictionary ,但是找到了一个数组。”,底层错误: 零))

我知道这与“站点”返回一个数组(单个数组)有关,但我不知道如何解决它。任何帮助将不胜感激。

解决方法

错误消息很明显,您需要解析对象数组而不是单个对象。

只需更改您的根声明属性

function change_active_parent($submenu_file)
{ 
    global $parent_file;

    $zone = 'edit-tags.php?taxonomy=zone&post_type=product';
    $storefront = 'edit-tags.php?taxonomy=storefront&post_type=product';
    $container = 'edit-tags.php?taxonomy=container&post_type=product';
    
    if (esc_html($zone) == $submenu_file) {
        $parent_file = 'parent';
        $submenu_file = $zone;
    }
    elseif (esc_html($storefront) == $submenu_file) {
        $parent_file = 'parent';
        $submenu_file = $storefront;
    }
    elseif (esc_html($container) == $submenu_file) {
        $parent_file = 'parent';
        $submenu_file = $container;
    }
    
    return $submenu_file;
}

add_filter( 'submenu_file','change_active_parent' );

let sites: APIResponseSites
,
**1.** First "sites" is an array so replace 

let sites: APIResponseSites

with

let sites: [APIResponseSites]()


**2.** As sites is a array collection,please print value like given below:

print(final.sites.first?.station_nm ?? "")
print(final.sites.first?.stage ?? 0.0)


Final code is here:


struct APIResponse: Codable {
        let sites: [APIResponseSites]()
    }
    
    struct APIResponseSites: Codable {
        let station_nm: String
        let stage: Float
    }
    
    
    let task = URLSession.shared.dataTask(with: url,completionHandler: {
            data,_,error in
            guard let data = data,error == nil else {
                return
            }
        
            var result: APIResponse?
            do {
                result = try JSONDecoder().decode(APIResponse.self,from: data)
            }
            catch {
                print("Failed to decode with error: \(error)")
            }
            
            guard let final = result else {
                return
            }
            
            print(final.sites.first?.station_nm ?? "")
            print(final.sites.first?.stage ?? 0.0)
            
    
        })