Swift3 和 JSON

Posted

技术标签:

【中文标题】Swift3 和 JSON【英文标题】:Swift3 and JSON 【发布时间】:2016-10-23 09:23:41 【问题描述】:

我正在尝试从我的服务器解析 JSON,但出现了奇怪的行为。

这是我的网络处理代码:

import Foundation


// Input: URLRequest
// Output: returns JSON or raw data


public let DANetworkingErrorDomain = "\(Bundle.main.bundleIdentifier!).NetworkingError"
public let MissingHTTPResponseError: Int = 10
public let UnexpectedResponseError: Int = 20

class NetworkProcessing

let request: URLRequest
lazy var configuration: URLSessionConfiguration = URLSessionConfiguration.default
lazy var session: URLSession = URLSession(configuration: self.configuration)


init(request: URLRequest) 
    self.request = request



//Construct a URLSEssion and download data and return the data

// This is multi Threading

typealias JSON = [String : Any]
typealias JSONHandler = (JSON?, HTTPURLResponse?, Error?) -> Void
typealias DataHandler = (Data?, HTTPURLResponse?, Error?) -> Void


func downloadJSON(completion: @escaping JSONHandler)
    let dataTask = session.dataTask(with: self.request) 
        (data, response, error) in

        //Off the main Thread
        //Error: missing http response

        guard let httpResponse = response as? HTTPURLResponse else 
            let userInfo = [NSLocalizedDescriptionKey : NSLocalizedString("Missing HTTP Response", comment: "")]

            let error = NSError(domain: DANetworkingErrorDomain, code: MissingHTTPResponseError, userInfo: userInfo)

            completion(nil, nil, error as Error)
            return
        


        //There was a response but no data
        if data == nil 
            if let error = error
                completion(nil, httpResponse, error)
            
          //We have some data
        else
            switch httpResponse.statusCode

            case 200:
                //Everything is good Parse the JSON into Foudation Object (array, dictionary..)
                do
                    let json = try JSONSerialization.jsonObject(with: data!, options: []) as? [String : Any]
                    completion(json, httpResponse, nil)
                 catch let error as NSError 
                    // The JSON data isn't correct
                    completion(nil, httpResponse, error)
                

                break


             // Any other http status code other than 200
            default:
                print ("Recieved HTTP response code: \(httpResponse.statusCode) = was not handeled in NetworkProcessing.swift")
                break

            
        


    

    dataTask.resume()




// This is raw data not JSON
func downloadData(completion: @escaping DataHandler) 
    let dataTask = session.dataTask(with: self.request) 
        (data, response, error) in

        //Off the main Thread
        //Error: missing http response

        guard let httpResponse = response as? HTTPURLResponse else 
            let userInfo = [NSLocalizedDescriptionKey : NSLocalizedString("Missing HTTP Response", comment: "")]

            let error = NSError(domain: DANetworkingErrorDomain, code: MissingHTTPResponseError, userInfo: userInfo)

            completion(nil, nil, error as Error)
            return
        


        //There was a response but no data
        if data == nil 
            if let error = error
                completion(nil, httpResponse, error)
            
            //We have some data
        else
            switch httpResponse.statusCode

            case 200:
                //Everything is good Parse the JSON into Foudation Object (array, dictionary..)
                completion(data, httpResponse, error)
                break


            // Any other http status code other than 200
            default:
                print ("Recieved HTTP response code: \(httpResponse.statusCode) = was not handeled in NetworkProcessing.swift")
                break

            
        


    

    dataTask.resume()



那我这样称呼它:

import UIKit

class ViewController: UIViewController 

    override func viewDidLoad() 
        super.viewDidLoad()

    let baseURL = "http://www.example.com/api/"
    let path = "business.php?tag=getBusCategories"
    let urlString = "\(baseURL)\(path)"

    let url = URL(string: urlString)!
    let urlRequest = URLRequest(url: url)
    let networkProcessing = NetworkProcessing(request: urlRequest)

    networkProcessing.downloadJSON  (json, httpResponse, error) in
        print(json)
        if let dictionary = json 

            if let busCategoriesDict = dictionary["busCategories"] as? [String : Any]
                let busCatName = busCategoriesDict["busCatName"]
                print("********************\(busCatName)*****************")
            
        
    


然后我在检查器中得到以下输出:

Optional(["busCategories": <__NSArrayI 0x6080000a7440>(

    busCatDescription = "Some description Some Description Some Description";
    busCatId = 1;
    busCatName = Accommodation;
,

    busCatDescription = "Some description Some Description Some Description";
    busCatId = 3;
    busCatName = "Bars & Restaurants";
,

    busCatDescription = "Some description Some Description Some Description";
    busCatId = 17;
    busCatName = Beauty;
,

    busCatDescription = "Some description Some Description Some Description";
    busCatId = 4;
    busCatName = Computer;
,

    busCatDescription = Description;
    busCatId = 18;
    busCatName = Conference;
,

    busCatDescription = "Some description Some Description Some Description";
    busCatId = 6;
    busCatName = Entertainment;
,

    busCatDescription = "Some description Some Description Some Description";
    busCatId = 11;
    busCatName = "Pets & Animals";
,

    busCatDescription = "Some description Some Description Some Description";
    busCatId = 12;
    busCatName = Services;
,

    busCatDescription = "Some description Some Description Some Description";
    busCatId = 10;
    busCatName = Stores;
,

    busCatDescription = Description;
    busCatId = 19;
    busCatName = Weddings;

)
, "success": 1, "error": 0])

我的问题在这里:

  ["busCategories": <__NSArrayI 0x6080000a7440>(

//the JSON looks like this:


    "error": false,
    "success": 1,
    "busCategories": [
        
            "busCatId": "1",
            "busCatName": "Accommodation",
            "busCatDescription": "Some description Some Description Some Description"
        , 
        "busCatId": "19",
        "busCatName": "Weddings",
        "busCatDescription": "Description"
    
]

我真的看不明白为什么 ios 没有正确解析 JSON,现在我无法引用 busCategories

【问题讨论】:

【参考方案1】:

如果我的理解是正确的,

dictionary["busCategories"]

不是[String:Any],而是[[String:Any]],换句话说,它是字典数组,而不是字典,因此

if let busCategoriesDict = dictionary["busCategories"] as? [String : Any]

永远不会成功。

【讨论】:

【参考方案2】:

不是 iOS 不能正确解析 JSON。是你。 ;-)

从输出中可以看出

可选(["busCategories": <__>NSArrayI 0x6080000a7440>

busCategories 是一个数组。

使用你的类型别名JSON 来明确。

if let dictionary = json 
    if let busCategoriesArray = dictionary["busCategories"] as? [JSON] 
        for busCategory in busCategoriesArray 
           let busCatName = busCategory["busCatName"] as! String
           print(busCatName)
        
    

【讨论】:

100% 正确,完美运行,3 天后,你花了 2 分钟

以上是关于Swift3 和 JSON的主要内容,如果未能解决你的问题,请参考以下文章

swift3 中的 SecKeyRawSign 和 SecKeyRawVerify

Swift3 和 JSON

仅在 Json Swift 3 中附加数组的第一项

swift3国家和电话代码选择器

Swift3 和 Segue:两个不同的 UITableViewController 指向一个 UIView

Swift3:我想读取和计数二维码