使用Swift Codable协议提取JSON片段
可编码协议确实有助于简化开发人员的生活。 它使我们能够将JSON响应转换为模型对象,而无需经历解析每个对象的繁琐过程。
我们如何在Swift中使用Codable协议?
为了更好地理解这个概念,让我们开始尝试一些编码示例:
Flickr 搜索JSON示例:
{
“ title”:“最近上传带标签的searchtag”,
“链接”:“ https:\ / \ /
www.flickr.com \ / photos \ / tags \ / searchtag \ /“,
“描述”:“”,
“已修改”:“ 2014–05–06T05:45:56Z”,
“生成器”:“ https:\ / \ /
www.flickr.com”,
“项目”:[{
“ title”:“ Bird \ / Pleasanton-CA”,
“链接”:“ https:\ / \ /
www.flickr.com \ / photos \ / geziyozbiz \ / 14140039213 \ /“,
“媒体”:{
“ m”:“ https:\ / \ / farm8.staticflickr.com \ / 7440 \ /14140039213_fe9c6fd0aa_m.jpg”
},
“ date_taken”:“ 2014–05–04T11:48:29–08:00”,
“说明”:“<a href = \” https:\ / \ /
www.flickr.com \ / people \ / geziyozbiz \ / \“> geziyozbiz 发布了一张照片:
让我们继续为上述json实现可编码协议。 Flickr feed响应具有一个词典,该词典包含标题,链接,描述,修改的内容,生成器和项目列表。
struct FlickrSearch:可编码{ 让标题:字符串? 让链接:字符串? 让描述:字符串? 让我们修改:字符串? let generator:字符串? 让物品:[物品]? 枚举 CodingKeys:字符串,CodingKey { 案例标题=“标题” 案例链接=“链接” 案例描述=“描述” 案例修改=“已修改” 案例生成器=“发电机” 案例项目=“物品”} init (来自解码器:解码器) 抛出 { 让值= 尝试解码器.container(keyedBy:CodingKeys。self)标题= 尝试值.decodeIfPresent(String。self,forKey:.title)链接= 尝试值 .decodeIfPresent(String。self,forKey:.link)描述= try values.decodeIfPresent(String。self,forKey:.description)modified = 尝试 values.decodeIfPresent(String。self,forKey:.modified)generator = try values.decodeIfPresent(String。self,forKey:.generator)items = try values.decodeIfPresent([Items]。self,forKey:.items)}}
同样,一个项目是一个字典,它具有一些属性和媒体字典,如下所示:
struct项目:可编码{ 让标题:字符串? 让链接:字符串? 让媒体:媒体? 让 date_taken:字符串? 让描述:字符串? 让发布:字符串? 让作者:字符串? 让 author_id:字符串? let标签:字符串? 枚举 CodingKeys:字符串,CodingKey { 案例标题=“标题” 案例链接=“链接” 案例媒体=“媒体” 案例 date_taken =“ date_taken” 案例描述=“描述” 案例发布=“已发布” 案例作者=“作者” 案例 author_id =“ author_id” 案例标签=“ tags”} 初始化 (来自解码器:解码器) 引发 { let values = try variables.container(keyedBy:CodingKeys。self)title = try values.decodeIfPresent(String。self,forKey:.title )link = 尝试值 .decodeIfPresent(String。self,forKey:.link)media = 尝试值 .decodeIfPresent(Media。self,forKey:.media)date_taken = 尝试值 .decodeIfPresent(String。self,forKey:.date_taken)描述= 尝试值 .decodeIfPresent(String。self,forKey:.description)已发布= 尝试值 .decodeIfPresent(String。self,forKey:.published)author = 尝试值 .decodeIfPresent(String。self,forKey:.author)author_id = 尝试 values.decodeIfPresent(String。self,forKey:.author_id)tags = 试试 values.decodeIfPresent(String。self,forKey:.tags)}}
媒体字典到Swift媒体可编码模型对象的转换 :
struct Media:可编码{ 让 m:字符串? 枚举 CodingKeys:字符串,CodingKey { case m =“ m”} 初始化 (来自解码器:Decoder) 抛出 { let值= 尝试解码器.container(keyedBy:CodingKeys。self)m = 尝试 values.decodeIfPresent(String。self,forKey: .m)}}
基础对象FlickrSearch是JSON的完整表示,我们将使用基础对象将JSON映射到Swift模型:
让url = URL(字符串:“ https://api.flickr.com/services/feeds/photos_public.gne?tags=%22%20+%20searchTag%20+%20%22&format=json&nojsoncallback=1”)
let task = URLSession.shared.dataTask(with:url!){(数据,响应,错误)在
让jsonDecoder = JSONDecoder()
让responseModel =试试jsonDecoder.decode(FlickrSearch.self,来自:数据!) }
task.resume()
按照上面的示例,我们可以编写从JSON到Swift模型的对象映射,并轻松地将完整的JSON解码为模型对象,但是,如果我们不需要仅完整对象的一部分,该怎么办。 假设我们只需要JSON响应中的items数组。 知道如何实现吗?
我们如何使用Codable协议提取JSON的一部分?
您可能会想,如果我们只需要JSON的一部分,为什么不能按照要求将JSON分解成几个部分。 是的,如果我们将JSON响应分成小部分,那就太好了。 它将使用低数据带宽。
仅当您使用内部实现的API时,以上解决方案才有可能。 但是,如果您正在使用第三方API,该怎么办。
我们是否需要使用Codable协议编写完整的JSON结构?
不,我们可以在没有完整的JSON对象映射的情况下实现此目标。 编写Items和Media的映射对象并转换Item的映射列表,如下所示:
让url = URL(字符串:“ https://api.flickr.com/services/feeds/photos_public.gne?tags=%22%20+%20searchTag%20+%20%22&format=json&nojsoncallback=1”)
let task = URLSession.shared.dataTask(with:url!){(数据,响应,错误)在
让jsonDecoder = JSONDecoder()
让dictionaryFromJSON =试试JSONSerialization.jsonObject(with:data !, options:.allowFragments)as! [String:Any]
让jsonItem = dictionaryFromJSON [“ items”]为? NSArray
让jsonData =尝试JSONSerialization.data(withJSONObject:jsonItem !,选项:[])
让responseModel =试试jsonDecoder.decode([Items] .self,来自:jsonData!)
}
task.resume()
正如我们在上面的代码中看到的,首先,我们需要将数据转换为JSON字典并将项目列表提取为NSArray。 将项目列表转换成数据,然后再次将数据解码到项目列表中。
希望你喜欢阅读!!! 学得很好…
如果您从本文中学到一点,对我来说将是一件很棒的事。 请拍拍手以表示支持!! 这将激励我写更多……。
有什么建议吗? 在下面的评论中提及。 我很乐意为他们工作。