JSON
JavaScript Object Notation,是輕量級的資料交換語言,與Swift的字典相當類似,使用key對應value,並且可以儲存String、Int、Double以及Array,透過JSON可以很方便的從別的平台取得資料,接著轉換成Swift程式語言可使用的格式。
{
"a" : "a",
"b" : 0,
"c" : 0.5,
"d" : [1,2,3,4,5],
"e" : {
"e1": "e"
}
}
以上是一個簡單的JSON結構,大括號【 {} 】代表物件,中括號【 [] 】代表陣列,一樣是使用
雙引號代表字串,冒號的左方為key,右方為value。
所以我們使用以上的JSON,拿字串a代表key的話,會取出字串a這個value,依此類推。
通常整個JSON是一個字串,我們可以透過轉換將JSON字串轉換成JSON,舉例來說,我們先使用字串構建一個JSON。
let jsonString = """
{
"a": "a",
"b": 1,
"c": 1.1
}
"""
我們可以到網站上驗證我們的JSON字串是否合法
確認是一個合法的JSON字串後,我們試著將它轉換成Swift可使用的資料格式,
前面有提到JSON其實與字典十分類似,因此你可以將JSON字串轉換成字典。
//將JSON字串轉換成Data
if let jsonData = jsonString.data(using: .utf8) {
do {
//透過JSON序列化轉換成自字典物件
if let dictionary = try JSONSerialization.jsonObject(with: jsonData, options: []) as? [String: Any] {
print(dictionary["a"]!) //a
print(dictionary["b"]!) //1
print(dictionary["c"]!) //1.1
}
} catch {
print(error.localizedDescription)
}
}
但是透過字典來取JSON其實還是有些麻煩,更好的作法應該是將JSON轉換成物件,不管是Class或Struct的形式均可,因此這邊說明如何將JSON轉換成物件。
首先我們必須要建立一個相同的物件格式,以上面的例子來說
struct MyJSONModel {
var a: String
var b: Int
var c: Double
}
接著我們必須遵循Codable協議
struct MyJSONModel: Codable {
var a: String
var b: Int
var c: Double
}
如此一來你就可以將JSON轉換成這個結構的實體
透過JSONDecoder來將JSON Data轉換成結構的實體
//將JSON字串轉換成Data
if let jsonData = jsonString.data(using: .utf8) {
do {
let jsonDecoder = JSONDecoder()
let myJSONModel = try jsonDecoder.decode(MyJSONModel.self, from: jsonData)
print(myJSONModel.a) //a
print(myJSONModel.b) //1
print(myJSONModel.c) //1.1
} catch {
print(error.localizedDescription)
}
}
當然反過來也可以,你可以將結構實體透過JSONEncoder轉換成JSON Data
let myJSONModel = MyJSONModel(a: "AA", b: 1, c: 0.2)
let jsonEncoder = JSONEncoder()
do {
let jsonData = try jsonEncoder.encode(myJSONModel)
} catch {
print(error.localizedDescription)
}
有幾個點必須注意的,你的struct或class定義的屬性,一定要與JSON一致,JSON的Value是整數就必須定義成整數,如果有些時候,這個值可能不存在,就必須定義成可選型別。
變數名稱也必須與JSON的Key相符,若是不相同,則會解析失敗,
有些時候JSON的Key可能與Swift的命名有些衝突,舉例來說有個JSON格式如下
{
"Name": "Jerry",
"Age": 18,
}
如果我們想要使用這個JSON,且是轉換成struct或class的話,就得這樣定義
struct User: Codable {
var Name: String
var Age: Int
}
但是我們都知道,Swift的命名規則,常數與變數名稱應該為小寫開頭的,因此這樣的命名不是太妥當
你可以一樣將變數命名成小寫,並增加一個enum CodingKeys,且資料型態為String,實作CodingKey這個Protocol。
struct User: Codable {
var name: String
var age: Int
enum CodingKeys: String, CodingKey {
case name = "Name"
case age = "Age"
}
}
enum的case為你的所有變數名稱,後方則是JSON對應的Key真正的樣子,如此一來,即使JSON的Key與Swift的命名有出入,也可以更換成我們習慣的命名規則。
let jsonString = """
{
"Name": "Jerry",
"Age": 18
}
"""
//將JSON字串轉換成Data
if let jsonData = jsonString.data(using: .utf8) {
do {
let jsonDecoder = JSONDecoder()
let user = try jsonDecoder.decode(User.self, from: jsonData)
print(user.name) //Jerry
print(user.age) //18
} catch {
print(error.localizedDescription)
}
}
此外,你可以解析JSONDecoder所拋出的例外
do {
let jsonDecoder = JSONDecoder()
let myJSONModel = try jsonDecoder.decode(JSONModel.self, from: jsonData)
} catch DecodingError.keyNotFound(let key, let context) {
} catch DecodingError.typeMismatch(let type, let context) {
} catch DecodingError.valueNotFound(let type, let context) {
} catch {
}
沒有留言:
張貼留言