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"
}
}