我需要使用嵌套的Json创建表视图

时间:2019-02-26 15:11:59

标签: json swift tableview

我必须从以下网址读取一个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?
}

1 个答案:

答案 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()

}