Swift 與 JSON 數據

?

轉載自:?http://www.cnblogs.com/theswiftworld/p/4660177.html

我們大家平時在開發 App 的時候,相信接觸最多的就是 JSON 數據了。只要你的 App 有讀取網絡數據的功能,你就免不了要與 JSON 打交道。比如你做一個新聞 App,你要讀取和解析新聞數據,這樣才能顯示給用戶。

那么我們今天就來了解一下 JSON 以及它在 App 中的應用吧。

在前兩節我們會介紹 JSON 數據格式,如果您已經對 JSON 比較了解了,那么也可以跳過前兩節,繼續閱讀后面的內容。

什么是 JSON

首先,JSON 的全稱叫做?JavaScript Object Notation?,翻譯成中文就是?JavaScript 對象表示法,是一種輕量級的數據交互格式。

JSON 數據分為三種形式,對象,數組,值。

對象是一個無序的“‘名稱/值’對”集合。一個對象以“{”(左括號)開始,“}”(右括號)結束。每個“名稱”后跟一個“:”(冒號);“‘名稱/值’ 對”之間使用“,”(逗號)分隔。

數組是值(value)的有序集合。一個數組以“[”(左中括號)開始,“]”(右中括號)結束。值之間使用“,”(逗號)分隔。

值(value)可以是雙引號括起來的字符串(string)、數值(number)、true、false、 null、對象(object)或者數組(array)。這些結構可以嵌套。

下面是一個簡單的例子:

{"firstname": "San","lastname" : "Zhang","age": 21, "friends": ["Mark","Li"] }

上面的數據示例,表示了這樣一個結構,首先我們的數據被一對大括號包圍,那么我們的數據就是?對象?類型,然后它里面有四個屬性,firstname,lastname,age,friends。 其中前兩個屬性?firstname?和?lastname?字符串類型,他們的值分別是?San?和?Zhang。?age?屬性代表年齡,所以它的值一個?Number?類型的?21

注意一下,字符串類型和數字類型的區別,字符串類型的值用一對雙引號括了起來,而數值類型不需要雙引號。

最后,friends?屬性的值是一個數組,用一對中括號包圍起來,而數組中的元素,仍然是字符串類型。

以上就是 JSON 的一個基本結構,關于 JSON 更詳細的介紹,可以參看?json.org

JSON 數據實例

我們看完了 JSON 的格式之后,那么我們就接著看一下具體的 JSON 數據是怎樣的格式呢?

比如這個天氣數據接口:?http://api.openweathermap.org/data/2.5/weather?q=China,bj&lang=zh_cn

如果我們在瀏覽器打開這個地址,我們就可以看到類似這樣的數據:

{"coord": {"lon": 116.4,"lat": 39.91 }, "weather": [ { "id": 520, "main": "Rain", "description": "陣雨", "icon": "09d" }, { "id": 701, "main": "Mist", "description": "薄霧", "icon": "50d" } ], "base": "stations", "main": { "temp": 300.39, "pressure": 1008, "humidity": 94, "temp_min": 297.15, "temp_max": 303.71 }, "visibility": 2300, "wind": { "speed": 1, "deg": 140 }, "clouds": { "all": 75 }, "dt": 1437281131, "sys": { "type": 1, "id": 7405, "message": 0.0136, "country": "CN", "sunrise": 1437253268, "sunset": 1437305986 }, "id": 1816670, "name": "Beijing", "cod": 200 }

我們來簡單看一下,數據整體使用一對大括號包圍的,也就是說返回給我們的數據,是一個?JSON 對象?緊接著,這個對象包含了?coord?屬性,這個屬性的值又是一個對象,里面有兩個屬性 'lon' 和 'lat' 代表地理位置,后面還有很多其他屬性代表天氣的數據。

JSON 數據格式,可以很結構化的表示出天氣的信息。而且數據結構一目了然,非常的清晰。并且有很多在線工具可以幫助大家更好的編輯和查看 JSON 數據。
比如?http://www.jsoneditoronline.org

Swift 中處理 JSON 數據

我們在了解過 JSON 數據后,就繼續我們的主題吧。

使用 NSJSONSerialization

Swift 中處理?JSON?數據方式有很多種。首先,由于 Swift 可以引用 Cocoa 原生庫,所以我們可以用 Cocoa 中的?NSJSONSerialization?來處理?JSON?數據,這個類也很好理解,它會將?JSON?數據,轉換成 Cocoa 中的?NSDictionary?和?NSArray。我們來看一下如何用?NSJSONSerialization?來處理:

let APIURL = "http://api.openweathermap.org/data/2.5/weather?q=China,bj&lang=zh_cn"if let url = NSURL(string: APIURL) { if let jsonData = NSData(contentsOfURL: url) { if let jsonObj:NSDictionary = NSJSONSerialization.JSONObjectWithData(jsonData, options: NSJSONReadingOptions.allZeros, error: nil) as? NSDictionary{ if let weathers:NSArray = jsonObj["weather"] as? NSArray { var weatherSummary = "北京天氣情況:" for weather in weathers { if let desc:String = weather["description"] as? String { weatherSummary += desc + " " } } print(weatherSummary) } } } }

讓我們來逐個講解。

  1. 首先,我們通過?let url = NSURL(string: APIURL)?來講天氣接口包裝成 NSURL。
  2. 然后,我們使用?let jsonData = NSData(contentsOfURL: url)?將這個 URL 的內容讀取下載,存放到?NSData?中。
  3. 接下來,我們就要使用?NSJSONSerialization?將這些數據解析成?JSON?了。
    let jsonObj:NSDictionary = NSJSONSerialization.JSONObjectWithData(jsonData, options: NSJSONReadingOptions.allZeros, error: nil) as? NSDictionary
    這里我們?JSONObjectWithData?方法將傳入的?NSData?數據解析成 JSON 對象,如果我們的?JSON?根節點是以對象形式存放的,那么我們得到的就是一個?NSDictionary。而如果是以數組形式存放的,那么我們得到的就是一個?NSArray?了。后面還有兩個參數?options?代表 JSON 讀取選項,這個我們稍后會講到,error?參數表示 JSON 讀取中的錯誤,如果傳入?nil?表示不接受錯誤消息。

  4. 我們得到了解析出來的 JSON 后,我們就可以像訪問普通集合對象那樣得到里面的信息了:

if let weathers:NSArray = jsonObj["weather"] as? NSArray { var weatherSummary = "北京天氣情況:" for weather in weathers { if let desc:String = weather["description"] as? String { weatherSummary += desc + " " } } print(weatherSummary) }

我們這里將天氣情況讀取出來,并打印到屏幕上,以我們上面的數據為例,打印到屏幕上就是這個樣子:

北京天氣情況:陣雨 薄霧

NSJSONSerialization 的讀取選項

就在剛剛,我們使用?NSJSONSerialization?成功的解析了 JSON 數據,覺得用起來很爽吧。仔細回想一下,我們剛才還注意到有一個?options?參數我們沒有詳細介紹。這個我們可以把它叫做讀取選項,這個參數的類型是?NSJSONReadingOptions,它的取值可以是以下幾種:

  1. MutableContainers: 讓返回的 JSON 數據中的數組和字典是可更改的。
  2. AllowFragments: 允許 JSON 返回的數據有多個根節點。
  3. MutableLeaves: 使 JSON 返回的字符串是可更改的。

相信部分膽大心細的朋友會發現。。。

我靠,這說的都是什么那,我還是不明白!

所以。。客官莫急,聽我一一道來。

  • MutableContainers

首先,MutableContainers?這個選項就讓返回的 JSON 集合可更改,讓我們來看一個例子就一目了然了:

var jsonString:NSString = "{\"names\":[\"James\",\"Jobs\",\"Tom\"]}" as NSString let jsonData = jsonString.dataUsingEncoding(NSUTF8StringEncoding) if let jsonObj:NSDictionary = NSJSONSerialization.JSONObjectWithData(jsonData!, options: NSJSONReadingOptions.MutableContainers, error: nil) as? NSDictionary { //操作之前 print(jsonObj) //James, Jobs, Tom if let nameArray:NSMutableArray = jsonObj["names"] as? NSMutableArray { nameArray.addObject("Cook") } //操作之后 print(jsonObj) //James, Jobs, Tom, Cook }

我們看一下吧,上面的代碼,我們在?JSONObjectWithData?方法調用的時候,加入了?NSJSONReadingOptions.MutableContainers?讀取參數, 這樣一來我們就可以更改我們的結果集了,我們注意到上面的這段代碼:

if let nameArray:NSMutableArray = jsonObj["names"] as? NSMutableArray { nameArray.addObject("Cook") }

取得?names?數組,并在里面增加一個新的項。隨后我們再次打印?jsonObj?對象,這次顯示的結果就是我們更改過的了。

如果我們在調用?JSONObjectWithData?方法的時候將?NSJSONReadingOptions.MutableContainers?選項去掉的話,我們就不能更改這里面任何數組的元素了。

第一個選項?MutableContainers?我們看完啦。 我們繼續

  • AllowFragments

還有另外一個選項參數,就是?AllowFragments?這個參數的官方解釋是允許被解析的 JSON 數據的根層級,不是數組和對象。

額。。 聽起來怪怪的不好理解是吧。

這個選項確實容易引起歧義,包括他的名稱?AllowFragments,翻譯成中文叫允許碎片, 什么叫允許碎片呢,我再自己實踐研究過這個之前我一直是這么認為的。。。

AllowFragments?的意思,是不是可以解析這樣的 JSON?

{"name":"Jobs"},{"name":"Ive"}

一段時間以來我的思維里是這么想的。可惜完全不是那么回事兒,如果你將這樣的 JSON 數據傳給?JSONObjectWithData?方法,你將得到一個無情的解析錯誤。。。

那么,這東西到底是干什么用的呀~

其實官方文檔上面說的清清楚楚,可以讓跟節點不是對象或者數組。在 JSON 中只有三種類型,對象,數組,值。

其實說白了就是這樣,允許你的 JSON 數據是一個字面值,比如字符串,數字,等等。

比如我們可以傳入一個原始的字符串

"something wrong about api"

這種數據,如果你打開了?AllowFragments, 是完全可以正常解析的(注意兩邊的雙引號,這個也包含在返回的數據中)。而如果你沒有打開這個選項,對于這種數據就會解析失敗了。

var jsonFragmentString = "\"something wrong about api\"" as NSStringlet jsonFragmentData = jsonFragmentString.dataUsingEncoding(NSUTF8StringEncoding) if let jsonObj: AnyObject = NSJSONSerialization.JSONObjectWithData(jsonFragmentData!, options: .AllowFragments, error: nil) { //使用 AllowFragments 選項,解析成功。 print(jsonObj) }

看完上面的代碼,相信大家瞬間就明白了,原來這家伙是做這個用的。

  • ** MutableLeaves **
    MutableLeaves?選項,這個選項讓我一直百思不得其解,文檔上說,使用了這個選項后,所有對象的葉子節點的字符串屬性,都會變成?NSMutableString,而我試遍多種文檔,也未驗證出來,得到的字符串依然是?NSString?而不是?NSMutableString

使用 NSJSONSerialization 創建 JSON 數據

剛才我們了解到如何用?NSJSONSerialization?來解析數據。同樣的,我們還可以使用?NSJSONSerialization?來構建 JSON 數據。

讓我們看一下下面的代碼:

let names = ["Jobs","Cook","Ive"]if let jsonData = NSJSONSerialization.dataWithJSONObject(names, options: NSJSONWritingOptions.allZeros, error: nil) { let jsonString = NSString(data: jsonData, encoding: NSUTF8StringEncoding) // ["Jobs","Cook","Ive"] }

我們使用?dataWithJSONObject?方法將 JSON 對象轉換成 JSON 數據,我們傳入的對象可以是數組也可以是字典,分別對應了 JSON 中的數組和對象。

我們注意到?dataWithJSONObject?這個方法也有個?options?選項,它用來控制構建 JSON 時的選項,類型為?NSJSONWritingOptions。它只有一個選項,就是?NSJSONWritingOptions.PrettyPrinted

這個選項的作用也不言而喻,就是讓生成的 JSON 數據是良好的格式化的:

let jsonObj = ["name":"Jobs","friends":["Ive","Cook"]] if let jsonData = NSJSONSerialization.dataWithJSONObject(jsonObj, options: NSJSONWritingOptions.PrettyPrinted, error: nil) { let jsonString = NSString(data: jsonData, encoding: NSUTF8StringEncoding) }

使用?PrettyPrinted?選項,我們輸出的 JSON 就是這樣一個良好格式化的:

{"name": "Jobs","friends": ["Ive","Cook" ] }

如果我們沒有使用這個選項,那么我們得到的輸出就是這樣:

{"name": "Jobs","friends": ["Ive","Cook"]}

區別就在這,這下明白了吧。

其他方案

當然了,除了使用原生的?NSJSONSerialization?來處理 JSON,我們還可以使用很多第三方庫來進行 JSON 數據的操作,比如:SwiftyJSON,?Argo。

限于篇幅以及大家的閱讀疲勞期,我們這篇文章只介紹原生的方式。后續還會為大家更詳細的講解這些第三方庫的運用,以及他們的好處及缺點。

下面是本篇文章對應的?playground?文件,大家下載下來應該應該能作為更好的參考:

swift-json.playground

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/458318.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/458318.shtml
英文地址,請注明出處:http://en.pswp.cn/news/458318.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

TeamViewer - 最好用強大的免費跨平臺遠程桌面控制軟件 (支持電腦和手機)

from:很早以前 LYcHEE 就提到過,家中的潮人爺爺奶奶每天擺弄著電腦,看看新聞發發郵件,安享晚年生活。只是意料之中的,電腦上莫名出現各種問題?不翼而飛的圖標?照片又忘記怎么導出了?…

【設計模式】7、橋接模式

橋接模式就是對一個類的方法進行抽象化,吧不相關的因素提取出來,發展出第二個類 1 package com.shejimoshi.structural.Bridge;2 3 4 /**5 * 功能:橋接模式使用6 * 意圖:將抽象部分與它的實現部分分離,使他們都…

hadoop HA 之 QJM

前言 本文主要通過對hadoop2.2.0集群配置的過程加以梳理,所有的步驟都是通過自己實際測試。文檔的結構也是根據自己的實際情況而定,同時也會加入自己在實際過程遇到的問題。搭建環境過程不重要,重要點在于搭建過程中遇到的問題,解…

TeamViewer免費版和付費版有什么不同

提到遠程控制軟件 TeamViewer無疑是目前業內知名度比較高的一款,所以說到遠程控制軟件可能大部分人首先想到的就是TeamViewer。在使用功能上,它支持遠程桌面控制、文件傳輸、遠程計算機鎖定、視頻會話、主控方和被控方身份互換,遠程管理無人執…

iOS-關于cell的重疊問題

記得很早之前遇到過一個問題,關于cell的重疊問題,現在回顧總結一下。 iOS中tableview的cell顯示是會消耗內存的,如果要顯示無數個cell,不可能把每個cell都存儲下來,為了解決這個問題,cell就用了重用機制&am…

每天一個Linux命令-ls

ls 命令在linux系統中是使用頻率最頻繁的幾個命令之一,直接使用不帶目錄名,是默認顯示當前目錄的文件及子目錄名稱,ls加指定目錄名,則可以查看指定目錄下的文件及子目錄名稱,ls不僅可以查看目錄下有哪些文件和子目錄,還…

halcon資料鏈接

本文轉載自xiamentingtao,原文地址如下: http://blog.csdn.net/xiamentingtao/article/details/52583787 1目錄(?)[]論壇培訓博客文檔書籍視頻論壇、培訓halcon學習網:http://www.ihalcon.com/鳥叔機器視覺:http://bbs.szvbt.com…

【代碼筆記】iOS-翻書效果的實現

代碼: RootViewController.m #import "RootViewController.h"interface RootViewController ()endimplementation RootViewController- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {self [super initWithNibName:…

修改TFS與本地源代碼映射路徑

使用源代碼管理資源管理器修改工作區 在“文件”菜單上單擊“源代碼管理”,再單擊“工作區”。 在“管理工作區”對話框的“名稱”列下,突出顯示要修改的工作區,然后單擊“編輯”。 在“編輯工作區”對話框中: 修改“名稱”框中…

halcon基礎知識

一、程序中的顏色: 綠色:注釋 褐色:控制開發 淺藍色:外部函數——HDevelop函數文件,可在所有Halcon程序中使用 深藍色:圖像獲取和處理 紫色:內部函數——本地程序函數,只在當前程序使…

停止過度設計,開發客戶需要的軟件

在與許多不同的團隊合作過之后,Greg Young發現大家做項目時經常會大幅度的過度設計。比如一個預計要開發9個月的項目,換個角度思考一下,卻可能只需要幾個星期就可以提交95%的功能。Young在最近倫敦舉行的DDD eXchange大會上著重闡述了這一點。…

Halcon—Tuple中符號的含義

2014年08月08日 21:20:30閱讀數:5429實例一(3d_coordinates.hdev):for I : 1 to NumImages by 1read_image (Image, calib/calib-3d-coord-I$02d)——C:\Program Files\MVTec\HALCON-10.0\images\的calib文件夾中開頭是calib-3d-c…

如果我是博客園的產品經理【上】

題記 這是一個系列文章的第一篇 我打算寫一個《如果我是XXX的產品經理》系列, 因為我是博客園的老用戶了,這個系列又是寫在博客園上的 所以先拿博客園開刀, 后面估計還會寫QQ音樂,有道云筆記,github,foxmai…

Halcon學習筆記(三)---數據類型

Halcon學習筆記(三)---數據類型halcon只能在單獨行進行注釋,不能在語句后面進行注釋。1、tuple(元組,重數)賦值符號“:”tuple算子:(1)變量定義與加減乘除運算代碼如下:*…

論文筆記之:RATM: RECURRENT ATTENTIVE TRACKING MODEL

RATM: RECURRENT ATTENTIVE TRACKING MODEL ICLR 2016 本文主要內容是 結合 RNN 和 attention model 用來做目標跟蹤。 其中模型的組成主要是: 1. an attention model 主要用來從輸入圖像中提取 patch; 2. RNN 用來預測 attention 參數,即&am…

【分享】WeX5的正確打開方式(5)——綁定機制

今天繼續WeX5的綁定機制。 需求分析 記賬本要實現的效果就是可以展示所有賬單,還能實時動態編輯每一筆賬單,官方案例的效果圖如下: 展示頁: 編輯頁 個人覺得官方案例加入了許多元素,不熟悉的同學每一個點都很難理解&am…

HALCON常用算子(HALCON13.0)

HALCON常用算子(HALCON13.0)Chapter 9--Developdev_clear_window ( : : : )功能:清除活動圖形窗口的內容dev_close_window ( : : : )功能:關閉活動圖形窗口。dev_display ( Object : : : )功能:在現有圖形窗口中顯示圖…

關于未捕獲異常的處理(WPF)

轉載自:http://www.cnblogs.com/chenxizhang/p/3280947.html 這一篇文章來談談對于WPF應用程序開發中的未捕獲異常的處理。 首先,我們當然是要求應用程序開發人員,盡可能地在程序可能出現異常的地方都去捕捉異常,使用try…catch的…

設計模式--23、訪問者模式

訪問者模式是一種較為復雜的行為型設計模式,它包含訪問者和被訪問元素兩個主要組成部分,這些被訪問的元素通常具有不同的類型,且不同的訪問者可以對它們進行不同的訪問操作。例如處方單中的各種藥品信息就是被訪問的元素,而劃價人…

C#串口SerialPort常用屬性方法

SerialPort(): //屬性 .BaudRate;獲取或設置波特率 .BytesToRead;得到 接收到數據的字節數 .BytesToWrites;得到送往串口的字節數 .DataBits;獲取或設置數據位 .IsOpen;獲取一個值,判斷串口是否打開 .Pariy;獲取或設置校驗位 .PortName;串口名稱 .ReadBufferSize;獲…