Correctly Parsing JSON in Swift 3

前端 未结 9 966
甜味超标
甜味超标 2020-11-21 07:00

I\'m trying to fetch a JSON response and store the results in a variable. I\'ve had versions of this code work in previous releases of Swift, until the GM version of Xcode 8

相关标签:
9条回答
  • 2020-11-21 07:54
    {
        "User":[
          {
            "FirstUser":{
            "name":"John"
            },
           "Information":"XY",
            "SecondUser":{
            "name":"Tom"
          }
         }
       ]
    }
    

    If I create model using previous json Using this link [blog]: http://www.jsoncafe.com to generate Codable structure or Any Format

    Model

    import Foundation
    struct RootClass : Codable {
        let user : [Users]?
        enum CodingKeys: String, CodingKey {
            case user = "User"
        }
    
        init(from decoder: Decoder) throws {
            let values = try? decoder.container(keyedBy: CodingKeys.self)
            user = try? values?.decodeIfPresent([Users].self, forKey: .user)
        }
    }
    
    struct Users : Codable {
        let firstUser : FirstUser?
        let information : String?
        let secondUser : SecondUser?
        enum CodingKeys: String, CodingKey {
            case firstUser = "FirstUser"
            case information = "Information"
            case secondUser = "SecondUser"
        }
        init(from decoder: Decoder) throws {
            let values = try? decoder.container(keyedBy: CodingKeys.self)
            firstUser = try? FirstUser(from: decoder)
            information = try? values?.decodeIfPresent(String.self, forKey: .information)
            secondUser = try? SecondUser(from: decoder)
        }
    }
    struct SecondUser : Codable {
        let name : String?
        enum CodingKeys: String, CodingKey {
            case name = "name"
        }
        init(from decoder: Decoder) throws {
            let values = try? decoder.container(keyedBy: CodingKeys.self)
            name = try? values?.decodeIfPresent(String.self, forKey: .name)
        }
    }
    struct FirstUser : Codable {
        let name : String?
        enum CodingKeys: String, CodingKey {
            case name = "name"
        }
        init(from decoder: Decoder) throws {
            let values = try? decoder.container(keyedBy: CodingKeys.self)
            name = try? values?.decodeIfPresent(String.self, forKey: .name)
        }
    }
    

    Parse

        do {
            let res = try JSONDecoder().decode(RootClass.self, from: data)
            print(res?.user?.first?.firstUser?.name ?? "Yours optional value")
        } catch {
            print(error)
        }
    
    0 讨论(0)
  • 2020-11-21 07:57

    This is an other way to solve your problem. So please check out below solution. Hope it will help you.

    let str = "{\"names\": [\"Bob\", \"Tim\", \"Tina\"]}"
    let data = str.data(using: String.Encoding.utf8, allowLossyConversion: false)!
    do {
        let json = try JSONSerialization.jsonObject(with: data, options: []) as! [String: AnyObject]
        if let names = json["names"] as? [String] {
            print(names)
        }
    } catch let error as NSError {
        print("Failed to load: \(error.localizedDescription)")
    }
    
    0 讨论(0)
  • 2020-11-21 07:59

    Updated the isConnectToNetwork-Function afterwards, thanks to this post.

    I wrote an extra method for it:

    import SystemConfiguration
    
    func loadingJSON(_ link:String, postString:String, completionHandler: @escaping (_ JSONObject: AnyObject) -> ()) {
    
        if(isConnectedToNetwork() == false){
            completionHandler("-1" as AnyObject)
            return
        }
    
        let request = NSMutableURLRequest(url: URL(string: link)!)
        request.httpMethod = "POST"
        request.httpBody = postString.data(using: String.Encoding.utf8)
    
        let task = URLSession.shared.dataTask(with: request as URLRequest) { data, response, error in
            guard error == nil && data != nil else { // check for fundamental networking error
                print("error=\(error)")
                return
            }
    
            if let httpStatus = response as? HTTPURLResponse , httpStatus.statusCode != 200 { // check for http errors
                print("statusCode should be 200, but is \(httpStatus.statusCode)")
                print("response = \(response)")
            }
            //JSON successfull
            do {
                let parseJSON = try JSONSerialization.jsonObject(with: data!, options: .allowFragments)
                DispatchQueue.main.async(execute: {
                    completionHandler(parseJSON as AnyObject)
                });
            } catch let error as NSError {
                print("Failed to load: \(error.localizedDescription)")
            }
        }
        task.resume()
    }
    
    func isConnectedToNetwork() -> Bool {
    
        var zeroAddress = sockaddr_in(sin_len: 0, sin_family: 0, sin_port: 0, sin_addr: in_addr(s_addr: 0), sin_zero: (0, 0, 0, 0, 0, 0, 0, 0))
        zeroAddress.sin_len = UInt8(MemoryLayout.size(ofValue: zeroAddress))
        zeroAddress.sin_family = sa_family_t(AF_INET)
    
        let defaultRouteReachability = withUnsafePointer(to: &zeroAddress) {
            $0.withMemoryRebound(to: sockaddr.self, capacity: 1) {zeroSockAddress in
                SCNetworkReachabilityCreateWithAddress(nil, zeroSockAddress)
            }
        }
    
        var flags: SCNetworkReachabilityFlags = SCNetworkReachabilityFlags(rawValue: 0)
        if SCNetworkReachabilityGetFlags(defaultRouteReachability!, &flags) == false {
            return false
        }
    
        let isReachable = (flags.rawValue & UInt32(kSCNetworkFlagsReachable)) != 0
        let needsConnection = (flags.rawValue & UInt32(kSCNetworkFlagsConnectionRequired)) != 0
        let ret = (isReachable && !needsConnection)
    
        return ret
    }
    

    So now you can easily call this in your app wherever you want

    loadingJSON("yourDomain.com/login.php", postString:"email=\(userEmail!)&password=\(password!)") { parseJSON in
    
        if(String(describing: parseJSON) == "-1"){
            print("No Internet")
        } else {
    
        if let loginSuccessfull = parseJSON["loginSuccessfull"] as? Bool {
            //... do stuff
        }
    }
    
    0 讨论(0)
提交回复
热议问题