Codable
是Swift史上最赞的功能之一。但是项目中我们可能会遇到下面的这种情况:服务器返回的json中同一个字段可能会解析成不同的类型。
{
"contents": {
"icon": "icon-name",
"font": "font-name"
}
}
{
"contents": "text"
}
contents
可能是icon font,也可能是普通的String
。这种情况我们如果用Decodable来处理呢?
方法1: Either
contents
可能是icon font或String
。或的关系我们可以定义一个枚举Either
来表示。
enum Either<T, U> {
case left(T)
case right(U)
}
我们可以利用Swift的conditional conformation特性,当T和U都是Decodable类型时候,Either也是Decodable。
extension Either: Decodable where T: Decodable, U: Decodable {
init(from decoder: Decoder) throws {
if let l = try? T(from: decoder) {
self = .left(l)
}
else if let r = try? U(from: decoder) {
self = .right(r)
}
else {
let context = DecodingError.Context(
codingPath: decoder.codingPath,
debugDescription: "Cannot decode \(T.self) or \(U.self)"
)
throw DecodingError.dataCorrupted(context)
}
}
}
实现很简单,首先尝试解析成T,如果不成功的话再尝试解析成U。如果都不成功则抛出异常。
利用Either
,我们就可以处理之前同一个字段可能解析成不同类型的问题了。
```swift
let iconJson = """
{
"contents": {
"icon": "icon-name",
"font": "font-name"
}
}
""".data(using: .utf8)!
let textJson = """
{
"contents": "text"
}
""".data(using: .utf8)!
struct IconFont: Decodable {
let icon: String
let font: String
Codable
是Swift史上最赞的功能之一。但是项目中我们可能会遇到下面的这种情况:服务器返回的json中同一个字段可能会解析成不同的类型。
{
"contents": {
"icon": "icon-name",
"font": "font-name"
}
}
{
"contents": "text"
}
contents
可能是icon font,也可能是普通的String
。这种情况我们如果用Decodable来处理呢?
方法1: Either
contents
可能是icon font或String
。或的关系我们可以定义一个枚举Either
来表示。
enum Either<T, U> {
case left(T)
case right(U)
}
我们可以利用Swift的conditional conformation特性,当T和U都是Decodable类型时候,Either也是Decodable。
extension Either: Decodable where T: Decodable, U: Decodable {
init(from decoder: Decoder) throws {
if let l = try? T(from: decoder) {
self = .left(l)
}
else if let r = try? U(from: decoder) {
self = .right(r)
}
else {
let context = DecodingError.Context(
codingPath: decoder.codingPath,
debugDescription: "Cannot decode \(T.self) or \(U.self)"
)
throw DecodingError.dataCorrupted(context)
}
}
}
实现很简单,首先尝试解析成T,如果不成功的话再尝试解析成U。如果都不成功则抛出异常。
利用Either
,我们就可以处理之前同一个字段可能解析成不同类型的问题了。
```swift
let iconJson = """
{
"contents": {
"icon": "icon-name",
"font": "font-name"
}
}
""".data(using: .utf8)!
let textJson = """
{
"contents": "text"
}
""".data(using: .utf8)!
struct IconFont: Decodable {
let icon: String
let font: String
Codable
是Swift史上最赞的功能之一。但是项目中我们可能会遇到下面的这种情况:服务器返回的json中同一个字段可能会解析成不同的类型。
{
"contents": {
"icon": "icon-name",
"font": "font-name"
}
}
{
"contents": "text"
}
contents
可能是icon font,也可能是普通的String
。这种情况我们如果用Decodable来处理呢?
方法1: Either
contents
可能是icon font或String
。或的关系我们可以定义一个枚举Either
来表示。
enum Either<T, U> {
case left(T)
case right(U)
}
我们可以利用Swift的conditional conformation特性,当T和U都是Decodable类型时候,Either也是Decodable。
extension Either: Decodable where T: Decodable, U: Decodable {
init(from decoder: Decoder) throws {
if let l = try? T(from: decoder) {
self = .left(l)
}
else if let r = try? U(from: decoder) {
self = .right(r)
}
else {
let context = DecodingError.Context(
codingPath: decoder.codingPath,
debugDescription: "Cannot decode \(T.self) or \(U.self)"
)
throw DecodingError.dataCorrupted(context)
}
}
}
实现很简单,首先尝试解析成T,如果不成功的话再尝试解析成U。如果都不成功则抛出异常。
利用Either
,我们就可以处理之前同一个字段可能解析成不同类型的问题了。
```swift
let iconJson = """
{
"contents": {
"icon": "icon-name",
"font": "font-name"
}
}
""".data(using: .utf8)!
let textJson = """
{
"contents": "text"
}
""".data(using: .utf8)!
struct IconFont: Decodable {
let icon: String
let font: String