swift 原生json解析探究与详解
2021-01-08 本文已影响0人
追忆之丘
swift 原生json解析探究与详解
我们先构建一个json数据
struct TextJson:Codable{
let status: Int
let text: String
}
然后我们生成json数据
let makeModel = TextJson(status:10,text:"json")
let jsonData = try JSONEncoder().encode(makeModel)
打印一下json数据
let jsonStr = String(data:jsonData, encoding: .utf8)
print(jsonStr)
//{"status": 10,"text":"json"}
现在我们解析一下json数据
let data = try JSONDecoder().decode(TextJson.self, from:jsonData)
print(data)
// TextJson(status:10, text:"json")
如果我们解析的数据不存在怎么办?按照以前的情况,确实会报错,但是swift里面引入了可选类型,解决了这个问题
我新建一个解析数据的model
struct NewModel:Codable{
let status: Int
let text: String
let isCheck: Bool
}
如果模型是这个样子,我们去解析jsonData的数据必出错,因为模型不匹配
得益于可选类型,我们只需要稍做修改,即可修复这个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)
现在报错的问题解决了,可是我们想给不存在的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))
我们惊喜的发现解析json数据的时候,当isCheck在jsonData里面不存在的时候,解析可以让ischeck有默认值false
让class遵循Codable去解析json数据
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)