我必须从以下网址读取一个json:https://randomuser.me/api/?results=100
我创建了People.swift文件,其中包含通过以下网站创建的结构:https://app.quicktype.io/?l=swift
我尝试使用此代码,但无法将json插入结构中,然后例如通过cell.people.name对其进行调用。
ViewController.swift:
var dataRoutine = [People]() // this is the structure that I created with the site indicated above.
这是我下载Json并解析的功能。
func downloadJsonData(completed : @escaping ()->()){
guard let url = URL(string: "https://randomuser.me/api/?results=100")else {return}
let request = URLRequest.init(url: url)
URLSession.shared.dataTask(with: request) { (data, response, error) in
if let httpResponse = response as? HTTPURLResponse {
let statuscode = httpResponse.statusCode
if statuscode == 404{
print( "Sorry! No Routine Found")
}else{
if error == nil{
do{
self.dataRoutine = try JSONDecoder().decode(People.self, from: data!)
DispatchQueue.main.async {
completed()
print(self.dataRoutine.count) // I don't know why my result is ever 1.
}
}catch{
print(error)
}
}
}
}
}.resume()
}
我的结构是:
import Foundation
struct People: Codable {
let results: [Result]?
let info: Info?
}
struct Info: Codable {
let seed: String?
let results, page: Int?
let version: String?
}
struct Result: Codable {
let gender: Gender?
let name: Name?
let location: Location?
let email: String?
let login: Login?
let dob, registered: Dob?
let phone, cell: String?
let id: ID?
let picture: Picture?
let nat: String?
}
struct Dob: Codable {
let date: Date?
let age: Int?
}
enum Gender: String, Codable {
case female = "female"
case male = "male"
}
struct ID: Codable {
let name: String?
let value: String?
}
struct Location: Codable {
let street, city, state: String?
let postcode: Postcode?
let coordinates: Coordinates?
let timezone: Timezone?
}
struct Coordinates: Codable {
let latitude, longitude: String?
}
enum Postcode: Codable {
case integer(Int)
case string(String)
init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
if let x = try? container.decode(Int.self) {
self = .integer(x)
return
}
if let x = try? container.decode(String.self) {
self = .string(x)
return
}
throw DecodingError.typeMismatch(Postcode.self, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Wrong type for Postcode"))
}
func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
switch self {
case .integer(let x):
try container.encode(x)
case .string(let x):
try container.encode(x)
}
}
}
struct Timezone: Codable {
let offset, description: String?
}
struct Login: Codable {
let uuid, username, password, salt: String?
let md5, sha1, sha256: String?
}
struct Name: Codable {
let title: Title?
let first, last: String?
}
enum Title: String, Codable {
case madame = "madame"
case mademoiselle = "mademoiselle"
case miss = "miss"
case monsieur = "monsieur"
case mr = "mr"
case mrs = "mrs"
case ms = "ms"
}
struct Picture: Codable {
let large, medium, thumbnail: String?
}
答案 0 :(得分:0)
主要问题是类型不匹配。
JSON的根对象不是People
数组,而是伞形结构,我将其命名为Response
请将结构更改为
struct Response: Decodable {
let results: [Person]
let info: Info
}
struct Info: Decodable {
let seed: String
let results, page: Int
let version: String
}
struct Person: Decodable {
let gender: Gender
let name: Name
let location: Location
let email: String
let login: Login
let dob, registered: Dob
let phone, cell: String
let id: ID
let picture: Picture
let nat: String
}
struct Dob: Decodable {
let date: Date
let age: Int
}
enum Gender: String, Decodable {
case female, male
}
struct ID: Codable {
let name: String
let value: String?
}
struct Location: Decodable {
let street, city, state: String
let postcode: Postcode
let coordinates: Coordinates
let timezone: Timezone
}
struct Coordinates: Codable {
let latitude, longitude: String
}
enum Postcode: Codable {
case integer(Int)
case string(String)
init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
if let x = try? container.decode(Int.self) {
self = .integer(x)
return
}
if let x = try? container.decode(String.self) {
self = .string(x)
return
}
throw DecodingError.typeMismatch(Postcode.self, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Wrong type for Postcode"))
}
func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
switch self {
case .integer(let x):
try container.encode(x)
case .string(let x):
try container.encode(x)
}
}
}
struct Timezone: Codable {
let offset, description: String
}
struct Login: Codable {
let uuid, username, password, salt: String
let md5, sha1, sha256: String
}
struct Name: Codable {
let title: Title
let first, last: String
}
enum Title: String, Codable {
case madame, mademoiselle, miss, monsieur, mr, mrs, ms
}
struct Picture: Codable {
let large, medium, thumbnail: String
}
几乎所有属性都可以声明为非可选属性,date
中的Dob
键是一个ISO8601日期字符串,您必须添加适当的日期解码策略。 People
数组是根对象的属性results
。
var dataRoutine = [Person]()
func downloadJsonData(completed : @escaping ()->()){
guard let url = URL(string: "https://randomuser.me/api/?results=100")else {return}
URLSession.shared.dataTask(with: url) { (data, response, error) in
if let httpResponse = response as? HTTPURLResponse {
let statuscode = httpResponse.statusCode
if statuscode == 404{
print( "Sorry! No Routine Found")
}else{
if error == nil{
do{
let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .iso8601
let jsonResponse = try decoder.decode(Response.self, from: data!)
self.dataRoutine = jsonResponse.results
DispatchQueue.main.async {
completed()
print(self.dataRoutine.count) // I don't know why my result is ever 1.
}
}catch{
print(error)
}
}
}
}
}.resume()
}