Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/json/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Swift JSONDecode解码数组/字典失败_Json_Swift_Jsondecoder - Fatal编程技术网

Swift JSONDecode解码数组/字典失败

Swift JSONDecode解码数组/字典失败,json,swift,jsondecoder,Json,Swift,Jsondecoder,这就是我使用的结构 struct earthquakeResults: Codable{ let datetime: String let depth: String //let eqid: Any let lat: String let lng: String let magnitude: String //let src: Any } 这是我试图获得JSON结果的时候,我使用地理编码器获得long/lat,然后使用它获得api调用的北

这就是我使用的结构

struct earthquakeResults: Codable{
    let datetime: String
    let depth: String
    //let eqid: Any
    let lat: String
    let lng: String
    let magnitude: String
    //let src: Any
}
这是我试图获得JSON结果的时候,我使用地理编码器获得long/lat,然后使用它获得api调用的北/南/东/西

let urlAsString = "http://api.geonames.org/earthquakesJSON?north=\(north)&south=\(south)&east=\(east)&west=\(west)&username=antoniogomez"

let url = URL(string: urlAsString)!
        let urlSession = URLSession.shared


        let jsonQuery = urlSession.dataTask(with: url, completionHandler: { data, response, error -> Void in
            if (error != nil) {
                print(error!.localizedDescription)
            }
            var err: NSError?

            let decoder = JSONDecoder()

            let jsonResult = try! decoder.decode([earthquakeResults].self, from: data!)

            if (err != nil) {
                print("JSON Error \(err!.localizedDescription)")
            }

            print(jsonResult)

            let dt = jsonResult[0].datetime
            let dp = jsonResult[0].depth
            let lt = jsonResult[0].lat
            let lg = jsonResult[0].lng
            let mag = jsonResult[0].magnitude

            let res = "Results : \(dt) \(dp) \(lt) \(lg) \(mag)"
            print(res)
})

        jsonQuery.resume()
我得到了一个错误:

线程3:致命错误:“重试!”表达式意外引发错误: Swift.DecodingError.typemistmatchswift.Array, Swift.DecodingError.ContextcodingPath:[],调试说明: 应解码数组,但找到了字典。, 参考误差:零

这就是JSON的样子:

{
    earthquakes =     (
                {
            datetime = "2012-10-09 10:32:04";
            depth = "10.2";
            eqid = c000d4li;
            lat = "-61.0333";
            lng = "153.9596";
            magnitude = "6.4";
            src = us;
        },
                {
            datetime = "2013-01-15 15:09:36";
            depth = 10;
            eqid = b000epcu;
            lat = "-62.5663";
            lng = "-161.3457";
            magnitude = "6.1";
            src = us;
        },
                {
            datetime = "2019-07-23 10:33:10";
            depth = 10;
            eqid = us70004r4f;
            lat = "-61.2936";
            lng = "154.063";
            magnitude = 6;
            src = us;
        },
                {
            datetime = "2016-01-31 17:43:40";
            depth = 10;
            eqid = us20004w6c;
            lat = "-63.2868";
            lng = "169.1522";
            magnitude = 6;
            src = us;
        },
                {
            datetime = "2016-02-23 18:10:40";
            depth = "7.71";
            eqid = us10004s4c;
            lat = "-63.1275";
            lng = "144.7936";
            magnitude = "5.9";
            src = us;
        },
                {
            datetime = "2017-06-03 19:32:50";
            depth = 10;
            eqid = us20009kit;
            lat = "-62.5792";
            lng = "155.834";
            magnitude = "5.9";
            src = us;
        },
                {
            datetime = "2010-12-24 04:48:54";
            depth = "10.7";
            eqid = c0000ueu;
            lat = "-63.5903";
            lng = "-167.4271";
            magnitude = "5.9";
            src = us;
        },
                {
            datetime = "2007-11-04 19:35:36";
            depth = "7.5";
            eqid = 2007jhax;
            lat = "-67.1317";
            lng = "111.5551";
            magnitude = "5.8";
            src = us;
        },
                {
            datetime = "2007-08-02 22:41:16";
            depth = "11.7";
            eqid = 2007fpab;
            lat = "-62.8736";
            lng = "145.4634";
            magnitude = "5.7";
            src = us;
        },
                {
            datetime = "2006-03-23 12:57:41";
            depth = 10;
            eqid = kqbp;
            lat = "-62.5198";
            lng = "164.8179";
            magnitude = "5.7";
            src = us;
        }
    );
}
这就是我最初所做的,但我不知道如何获取日期时间、大小或任何其他细节,所以我想我应该尝试使用解码器:

var jsonResult = (try! JSONSerialization.jsonObject(with: data!, options: JSONSerialization.ReadingOptions.mutableContainers)) as! NSDictionary
if (err != nil) {
    print("JSON Error \(err!.localizedDescription)")
}

从响应中,您将得到一个json,而不是包含预期json对象列表的json数组。因此,您的响应将被解码为具有该列表的对象。创建如下所示的数据类型

struct Result: Codable {
    let earthquakes: [Earthquake]

    enum CodingKeys: String, CodingKey {
        case earthquakes = "earthquakes"
    }
}

// MARK: - Earthquake
struct Earthquake: Codable {
    let datetime: String
    let depth: String
    let lat: String
    let lng: String
    let magnitude: String

    enum CodingKeys: String, CodingKey {
        case datetime = "datetime"
        case depth = "depth"
        case lat = "lat"
        case lng = "lng"
        case magnitude = "magnitude"
    }
}
并将结果解析为

let urlAsString = "http://api.geonames.org/earthquakesJSON?north=\(north)&south=\(south)&east=\(east)&west=\(west)&username=antoniogomez"

let url = URL(string: urlAsString)!
        let urlSession = URLSession.shared


        let jsonQuery = urlSession.dataTask(with: url, completionHandler: { data, response, error -> Void in
            if (error != nil) {
                print(error!.localizedDescription)
            }
            var err: NSError?

            let decoder = JSONDecoder()

            let jsonResult = try! decoder.decode(Result.self, from: data!)

            if (err != nil) {
                print("JSON Error \(err!.localizedDescription)")
            }

            print(jsonResult.earthquakes)

            let dt = jsonResult.earthquakes[0].datetime
            let dp = jsonResult.earthquakes[0].depth
            let lt = jsonResult.earthquakes[0].lat
            let lg = jsonResult.earthquakes[0].lng
            let mag = jsonResult.earthquakes[0].magnitude

            let res = "Results : \(dt) \(dp) \(lt) \(lg) \(mag)"
            print(res)
})

        jsonQuery.resume()

卡姆兰的上述回答很好

但是,您需要更改plist文件中的应用程序传输安全设置,以允许的链接获取数据。。。像这样:

<key>NSAppTransportSecurity</key>
<dict>
    <key>NSExceptionDomains</key>
    <dict>
        <key>api.geonames.org</key>
        <dict>
            <key>NSIncludesSubdomains</key>
            <true/>
            <key>NSThirdPartyExceptionAllowsInsecureHTTPLoads</key>
            <true/>
        </dict>
    </dict>
</dict>

错误信息说明了一切。为什么要显式编码键?如果键与结构成员匹配,则不需要它们。@没错,可以删除它们。实际上,我使用这个[web app]app.quicktype.io创建类型并按原样粘贴。
</plist>
</dict>
    struct Earthquake: Codable {
    let datetime: String
    let depth: Double
    let lat: Double
    let lng: Double
    let magnitude: Double

    enum CodingKeys: String, CodingKey {
        case datetime = "datetime"
        case depth = "depth"
        case lat = "lat"
        case lng = "lng"
        case magnitude = "magnitude"
    }
}