【问题标题】:When to use NSDictionary & NSArray during HTTP requests and JSON parsing?在 HTTP 请求和 JSON 解析期间何时使用 NSDictionary 和 NSArray?
【发布时间】:2015-06-12 07:46:14
【问题描述】:

在您发出 HTTP 请求并取回 JSON 数据时,我有一个关于何时使用 NSDictionary 和何时使用 NSArray 的问题。

例如,如果返回的 JSON 是 对象数组,如下所示:

   [
      {object1},
      {object2},
      .........
   ]

我的代码中有以下行:

 if let books:Array<AnyObject> = json[""] as? Array<AnyObject> {
 }

它给出一个错误:

数组?不能转换为 Array

解析:

var json:NSMutableArray = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: nil) as! NSMutableArray
            if (jsonError != nil) {
                println("Error parsing json: \(jsonError)")
            }

知道我可能做错了什么。

更新:

目前我有以下代码:

class func getBooks(completion: (result:Array<BookSummary>)->()) {

    var bookArray = [BookSummary]()
    let url = NSURL(string: "http://something.herokuapp.com/user/all")
    if let tempUrl:NSURL = url {
        let urlReq = NSURLRequest(URL: tempUrl)
        let queue = NSOperationQueue()
        NSURLConnection.sendAsynchronousRequest(urlReq, queue: queue, completionHandler: { (response: NSURLResponse!, data: NSData!, error: NSError!) -> Void in
            if (error != nil) {
                println("API error: \(error), \(error.userInfo)")
            }
            var jsonError:NSError?
            var newBook = BookSummary(id: "", title: "", fullname: "", thumbnail: "")
            if let arr = NSJSONSerialization.JSONObjectWithData(data, options: nil, error: nil) as? [AnyObject] {
                for a in arr {
                    //println(a)
                    //println( arr[0])
                     println( arr[0])
                }
            }     

通过 println(arr[0]) 我在第一个索引处获取对象。

但如果我尝试println(arr[0].fullname) 会出现错误:

任何对象都没有名为 fullname 的成员

【问题讨论】:

  • @Arbitur 感谢您的回复。那么什么是正确的方法。我有一个返回 JSON 的 API。但我似乎无法解析它。 swift中的HTTP请求和解析JSON是否涉及任何具体步骤
  • 你是如何提出请求的?
  • 我的错,一个 json 实际上可以作为一个数组开始。你是怎么解析的?你在使用 NSJSONSerialization 吗?
  • @Arbitur 感谢您的回复。是的,我正在使用 NSJSONSerialization。请参阅上面已编辑的帖子。我想做的就是发出一个 HTTP 请求,取回 JSON 数据,解析它并在我认为合适的时候使用它。我已经坚持了好几天了。在javascript中很容易做到这一点。因为有具体的步骤要遵循,但我对 swift 感到非常困惑,因为我没有看到任何具体的步骤。
  • 请看我的回答

标签: ios json swift


【解决方案1】:

如果您使用标准 NSJSONSerialization 从 JSON 字符串解析,则使用 JSONObjectWithData() 类函数。

这会返回 AnyObject?并且可以解析为字典或数组。

因此,如果 JSON 字符串以“[”开头,则它可以解析为数组:

if let arr = NSJSONSerialization.JSONObjectWithData(data, options: nil, error: nil) as? [AnyObject] { 
     for a in arr {
         println(a)
     }

     // Other options to access the values
     println( arr[0] )
     println( arr.first )
}

如果它以“{”开头,则它可以解析为字典:

if let dict = NSJSONSerialization.JSONObjectWithData(data, options: nil, error: nil) as? [String:AnyObject] { 
     for (key, value) in dict {
         println("\(key) = \(value)")
     }

     // Other options to access the values
     println( dict["someKey"] )
     println( dict[dict.keys[0]] )
     println( dict[dict.keys.first] )
}

在 Swift 中,我建议你不要使用 NSDictionary 和 NSArray,而是使用 Swift 自己的 Dictionary 和 Array。主要是因为 Swift 的类型非常安全,您可以控制 Swift 字典和数组上的类型,而不是旧的 NS 东西。

【讨论】:

  • 非常感谢。这为我清除了很多东西。通过使用您的代码,我将整个 JSON 记录在控制台上。但是我如何获得一个特定的值。例如,数组中的每个对象都有一个“全名”属性。我试过这个“println(a.fullname)”但是没有用。进一步解析 JSON 数据的正确方法是什么。所以我可以检索特定的值。再次感谢您
  • 如果它被解析成字典,你会得到一个键的值。 dict["fullname"] 这将返回 AnyObject?或任何你施放的东西。
  • 请记住,Javascript 中的 JSON 对象是真正的 OBJECT,因此您只需执行 .property 并获取值即可。但在大多数其他语言中,Swift 包含的 JSON 对象并不是真正的 OBJECT,它只是一个格式化的字符串,必须解析为该语言可以使用的东西。
  • 在这种情况下是字典。字典的值可以通过一个键访问,通常是一个字符串,但也可以是其他东西,比如 Int。语法如下所示:dict[key] 并返回一个值。
  • 当我的 JSON 以“[”开头时,我已将其解析为一个数组。正如您在上面的答案中所做的那样。我现在需要解析成字典以便 swift 可以理解吗?
【解决方案2】:

从包含 Products/Price/Name 的 CDiscount API 解析此 json 数据:

{
        "ItemCount": "34",
        "PageCount": "7",
        "PageNumber": "0",
        "Products": [
        {
        "AssociatedProducts": null,
        "BestOffer": {
            "Condition": "New",
            "Id": "MD531NFA",
            "IsAvailable": true,
            "PriceDetails": {
                    "Discount": null,
                    "ReferencePrice": "249.00",
                    "Saving": {
                        "Type": "Amount",
                        "Value": "17.0"
                        }
                },
            "ProductURL": "http://www.cdiscount.com/opa.aspx/?trackingid=T1mQnsY6DVL2nQMfDBv95HJiDedNp6Iusby9wMMBIWJ8xCUTe2ax25EOmRJ_4IkI&action=product&id=MD531NFA",
            "SalePrice": "231.98",
            "Seller": {
                "Id": "0",
                "Name": "Cdiscount"
                },
            "Shippings": null,
            "Sizes": null
            },
        "Brand": "APPLE",
        "Description": "Tablette tactile avec écran 7,9\" capacitif - Processeur Apple A5 bicoeur - Stockage 16Go - WiFi 802.11 b/g/n - Camera avant 1,2Mpixels - Caméra arrière 5Mpixels - Connecteur Lightning reversible - Jusqu’à 10h d'autonomie - IOS 6 - Garantie 1 an",
        "Ean": null,
        "Id": "MD531NFA",
        "Images": null,
        "MainImageUrl": "http://i2.cdscdn.com/pdt2/N/F/A/1/300x300/MD531NFA.jpg",
        "Name": "Apple iPad mini Wi-Fi 16 Go blanc & argent",
        "Offers": null,
        "OffersCount": "10",
        "Rating": "4.69"
        }
        ]
    }

根据这些数据,我想打印产品名称及其价格。 所以我应该首先将 Json 对象解析为字典以搜索“Products”键,并将结果解析为 AnyObject。

let products: AnyObject = jsonDict["Products"]    

然后遍历所有产品,并为每个产品遍历字典键

for aProduct in products as! NSArray{

        for aKey in (aProduct as! NSDictionary).allKeys{

基于json数据模型,打印产品名称即可:

if aKey as! String == "Name"{
                    if let name: AnyObject = aProduct["Name"]{
                        println("Product : \(name) ->")
                    }
                }

但是我需要在数据树中更深入地打印价格,因为它存储在另一个字典字典中。

if aKey as! String == "BestOffer"{
                if let offers: AnyObject = aProduct["BestOffer"]{
                    for offerDetail in (offers as! NSDictionary).allKeys{
                        if offerDetail as! String == "SalePrice"{
                            if let price: AnyObject = offers["SalePrice"]{
                                println("|--> Price: \(price)")
                            }
                        }

                    }
                }
            }

所以继续:

// Get data in a swift Dictionary
let jsonDict = NSJSONSerialization.JSONObjectWithData(responseData, options: NSJSONReadingOptions.AllowFragments, error: nil) as? [String: AnyObject]


// Begin navigate through the dictionary (here through 'Products')
if let products: AnyObject = jsonDict["Products"]{
        // Get product data through loop in a NSArray
        for aProduct in products as! NSArray{
            // Loop over keys in one product as NSDictionary
            for aKey in (aProduct as! NSDictionary).allKeys{
                // test key value
                if aKey as! String == "Name"{
                    // if exists, print product name
                    if let name: AnyObject = aProduct["Name"]{
                        println("Product : \(name) ->")
                    }
                }
                // another test key value
                if aKey as! String == "BestOffer"{
                    // same as before to get deeper in the json tree structure
                    if let offers: AnyObject = aProduct["BestOffer"]{
                        for offerDetail in (offers as! NSDictionary).allKeys{
                            if offerDetail as! String == "SalePrice"{
                                if let price: AnyObject = offers["SalePrice"]{
                                    println("|--> Price: \(price)")
                                }
                            }

                        }
                    }
                }
            }

        }

    }

希望这会有所帮助!

【讨论】:

  • 很高兴能帮上忙!
【解决方案3】:

看了你的评论,我想你想看看AFNetworking

简单示例:

AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
[manager GET:@"http://example.com/resources.json" parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
    NSLog(@"JSON: %@", responseObject);
    // here is where you import the JSON data from responseObject

} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
    NSLog(@"Error: %@", error);
}];

NSDictionary 未排序,但具有关联性,NSArray 已排序但仅索引。一种方法是将JSON数据的所有键获取到NSArray中,这样数据结构的顺序保持不变,然后将数据导入NSDictionary。然后你可以使用keys数组中的值来引用NSDictionary

这个例子是针对 Objective-C 的,但希望它仍然是相关的

【讨论】:

    猜你喜欢
    • 2011-09-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-10
    • 1970-01-01
    相关资源
    最近更新 更多