Swift利用Decodable解析JSON的一个小问题详解
前言
Swift4是苹果计划于2017年秋季推出的最新版本,其主要重点是提供与Swift3代码的源兼容性,并努力实现ABI稳定性。从Swift4开始提供的Decodable解析JSON确实很方便,但遇到一个小问题,记录一下。
当JSON中某个key的值为{}或者空字符串”“,而该值需要解析的不是基本类型时,即使标记为Optional,依然会导致整个解析失败:
//:Playground importFoundation //Book.swift structBook:Codable{ varid:Int varname:String varcover:BookCover? enumCodingKeys:String,CodingKey{ caseid casename casecover } structBookCover:Codable{ varurl:String varthumbURL:String enumCodingKeys:String,CodingKey{ caseurl casethumbURL="thumb_url" } } } //JSON letbookJSON1= """ { "id":1, "name":"fakename1", "cover":{ "url":"a.png", "thumb_url":"b.png" } } """ letbookJSON2= """ { "id":2, "name":"fakename2", "cover":{ } } """ //解析 letdecoder=JSONDecoder() decoder.dateDecodingStrategy=.iso8601 letbook1=try?decoder.decode(Book.self,from:bookJSON1.data(using:.utf8)!) //解析正常 print(book1) letbook2=try?decoder.decode(Book.self,from:bookJSON2.data(using:.utf8)!) //输出nil,cover已经是Optional,为何整个book都解析失败? print(book2)
原因:
因为cover是Optional,所以会调用decodeIfPresent来解析,而在cover节点中没有找到url,thumb_url这两个key,导致默认解析失败,直接抛出了错误。
解决:
重新实现decodeIfPresent,在解析失败时返回nil而不是抛出错误导致整个解析失败:
extensionKeyedDecodingContainer{ publicfuncdecodeIfPresent(_type:T.Type,forKeykey:K)throws->T?whereT:Decodable{ returntry?decode(type,forKey:key) } }
参考:http://davelyon.net/2017/08/16/jsondecoder-in-the-real-world
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对毛票票的支持。