swift

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)
上一篇下一篇

猜你喜欢

热点阅读