swift 原生json解析探究與詳解
我們先構建一個json數(shù)據(jù)
struct TextJson:Codable{
let status: Int
let text: String
}
然后我們生成json數(shù)據(jù)
let makeModel = TextJson(status:10,text:"json")
let jsonData = try JSONEncoder().encode(makeModel)
打印一下json數(shù)據(jù)
let jsonStr = String(data:jsonData, encoding: .utf8)
print(jsonStr)
//{"status": 10,"text":"json"}
現(xiàn)在我們解析一下json數(shù)據(jù)
let data = try JSONDecoder().decode(TextJson.self, from:jsonData)
print(data)
// TextJson(status:10, text:"json")
如果我們解析的數(shù)據(jù)不存在怎么辦妓湘?按照以前的情況居兆,確實會報錯,但是swift里面引入了可選類型,解決了這個問題
我新建一個解析數(shù)據(jù)的model
struct NewModel:Codable{
let status: Int
let text: String
let isCheck: Bool
}
如果模型是這個樣子,我們去解析jsonData的數(shù)據(jù)必出錯,因為模型不匹配
得益于可選類型爷贫,我們只需要稍做修改,即可修復這個bug
struct NewModel:Codable{
let status: Int
let text: String
let isCheck: Bool? //這里做了改動
}
let data = try JSONDecoder().decode(TextJson.self, from:jsonData)
print(data)
// TextJson(status:10, text:"json", isCheck: nil)
現(xiàn)在報錯的問題解決了补憾,可是我們想給不存在的key增加一個默認值怎么辦漫萄?比如我們想給isCheck的默認值設置為false,而不是沒有這個key的時候是nil
通過研究swift的JSONDecoder的源碼盈匾,我們可以對KeyedDecodingContainer進行擴展腾务,以滿足我們的需求
extension KeyedDecodingContainer{
public func decodeIfPresent(_ type: Bool.Type, forKey key: K) throws -> Bool?{
if let value = try? decode(type, forKey: key) {
return value
}
return false
}
}
然后我們在進行解析看看
let data = try JSONDecoder().decode(TextJson.self, from:jsonData)
print(data)
//TextJson(status:10, text:"json", isCheck: Optional(false))
我們驚喜的發(fā)現(xiàn)解析json數(shù)據(jù)的時候,當isCheck在jsonData里面不存在的時候削饵,解析可以讓ischeck有默認值false
讓class遵循Codable去解析json數(shù)據(jù)
class TextClassJson: Codable{
let status: Int
let text: String
init(status: Int, text:String){
self.status = status
self.text = text
}
}
let data = try JSONDecoder().decode(TextClassJson.self, from:jsonData)
print(data.status, data.text)
// 10 json
如果我們也想讓上面的model解析isCheck這個不存在的key呢,
class TextClassJson: Codable{
let status: Int
let text: String
let isCheck: Bool
init(status: Int, text:String, isCheck: Bool){
self.status = status
self.text = text
self.isCheck = isCheck
}
}
let data = try JSONDecoder().decode(TextClassJson.self, from:jsonData)
print(data.status, data.text, data.isCheck)
// 報錯岩瘦,因為沒有與isCheck匹配的key
我們如何修改?
class TextClassJson: Codable{
let status: Int
let text: String
let isCheck: Bool?
init(status: Int, text:String){
self.status = status
self.text = text
}
}
let data = try JSONDecoder().decode(TextClassJson.self, from:jsonData)
print(data.status, data.text, data.isCheck)
// 10 json Optional(false)