在Swift 4中关于JSON解析的简短思考
首先,将Codable定义为typealias Codable = Decodable&Encodable,我们采用两种必需的协议:
- 可解码 :解析JSON(获取响应)
–通过解码JSONData,我们将接收/读取数据
2. Encodable :生成JSON(响应后)
–要将可编码 类型转换为Data 。
它适用于基本类型(Int,String和Float等),某些基础类型(数据,URL,日期等)以及数组,字典和可选参数(枚举)。
- NSData
- NSString
- NSNumber
- UInt
- Int
- Float
- Double
- Bool
- NSDate
- NSArray
- NSDictionary
为什么?
- 在我们的数据管理器中简化依赖关系
- 将数据结构转换为JSON数据从未如此简单(hmmmm ..),允许开发人员将JSON数据存储到磁盘或将其编码为
URLRequest
的httpBody :)。
您可以编写一个使用外部来源的JSON或通过存根进行测试的应用。 这里的开始问题是您在应用程序中建模的概念的结构与JSON生产者建模的概念之间的不一致。 在您的应用中更改和使用JSON结构的一些示例:
- 使用CodingKey更改名称属性
2.通过手动编码和解码简化复杂的结构
3.使用嵌套数据(数组JSON内的数组)
对于1.,即使我们不必解析JSON表示形式的每个元素,我们也需要创建与JSONData中名称相同的属性,或者使用CodingKey重命名它们以直接存储基本示例。 到目前为止很简单!🤠🤠
struct SurfBoard:可编码{
var品牌:字符串
var size:大小
枚举CodingKeys:字符串,CodingKey {
案例品牌=“名称”
大小
}
}
struct大小:可编码{
宽度:双
var高度:Double
}
注意:对于在NULL元素中声明的JSON属性,我们需要使用❓Optional镜像该实例。 这样,就不会因为输入错误或对JSON提供程序的保证产生误解而使数据无提示地丢失。
对于2.,在这种情况下,您可以提供自己的可编码和可解码的自定义逻辑od来定义自己的编码和解码逻辑。 您需要显式实现Encodable和Decodable协议的encode(to 🙂和init(from 🙂方法。
struct SurfBoard {
var品牌:字符串
var size:大小
枚举CodingKeys:字符串,CodingKey {
案例品牌=“名称”
情况宽度
情况高度
}
}
扩展程序SurfBoard:可编码{
func encode(编码器:编码器)抛出{
var container = encoder.container(keyedBy:CodingKeys.self)
尝试container.encode(brand,forKey:.title)
尝试container.encode(size.width,forKey:.width)
尝试container.encode(size.height,forKey:.height)
}
}
扩展程序SurfBoard:可解码{
init(来自解码器:解码器)抛出{
让值=尝试解码器。容器(keyedBy:CodingKeys.self)
品牌=尝试values.decode(String.self,forKey:.brand)
让width =试试values.decode(Double.self,forKey:.width)
让高度=尝试values.decode(Double.self,forKey:.height)
大小=大小(宽度:宽度,高度:高度)
}
}
您可以在这里获得不错的使用场景✅。
对于3.在这种情况下的嵌套数据,您需要解码和读取JSON。 可解码类型用作可以安全解码的中间类型。 它充当初始化程序中的数据源,用于您将在应用程序其余部分中使用的类型。
//与外部JSON快速实现结构不兼容
struct SurfBoard {
var品牌:字符串
var产品:[产品]
结构产品:可编码{
变量名称:字符串
var点:整数
var说明:字符串?
}
}
API返回的JSON包含的信息多于填充相应Swift类型所需的信息。
//嵌套数组所需的快速结构
struct SurfBoardService:可解码{
让品牌:字符串
让过道:[过道]
结构过道:可分解{
命名:字符串
让架子上:[架子]
结构架:可分解的{
命名:字符串
让产品:SurfStore.Product
}
}
}
该扩展添加了一个带有SurfBoardService实例的初始化程序,并通过循环并丢弃过道和架子来消除不必要的嵌套。
要从外部数组中提取所需的数据,请编写一个与源JSON形状相似的类型,并将其标记为Decodable。 然后,在您将在应用程序其余部分中使用的类型上编写一个初始化程序,该初始化程序采用镜像源JSON的类型的实例。
扩展SurfStore {
init(来自服务:SurfBoardService){
品牌= service.brand
产品= []
用于服务通道。
用于在过道中的货架{
products.append(shelf.product)
}
}
}
}
在该说明上:
扩展只能提供便捷的初始化程序
- 由于协议一致性而实现的初始化程序必须标记为
required
(在类上)。 -
required init
只能在类的主体内实现。 - 由于没有继承,因此结构可以在扩展程序中具有初始化程序。
并最终阅读嵌套的JSON…
让解码器= JSONDecoder()
让serviceStores =试试decoder.decode([SurfBoardService] .self,来自:json)
让商店= serviceStores.compactMap {SurfBoard(from:$ 0)}
用于商店{
print(“ \(store.name)正在销售:”)
用于商店中的产品。products{
print(“ \ t \(product.name)(\(product.points)points)”)
如果让description = product.description {
打印(“ \ t \ t \(描述)”)
}
}
}
文档中的更多内容:合并来自不同深度的数据
如有任何疑问,请随时发表评论🙂 谢谢!
参考:
https://hackernoon.com/everything-about-codable-in-swift-4-97d0e18a2999
http://aplus.rs/2017/highly-maintainable-app-architecture/