解码嵌套对象swift4 Codable
Decoding nested object swift4 Codable
API 发给我这个 json :
{
"name": "John Doe",
"details": [{
"name": "exampleString"
}, {
"name": [1, 2, 3]
}]
}
这里的问题是细节数组有两个不同值类型的字典。
如何使用 swift4 的可解码协议在模型中解码这个 json ?
我不建议您使用异构类型构建 JSOn;在这种情况下 details.name 可以是字符串或 Int 数组。虽然你可以做到这一点 Swift,但它有点混乱,因为它默认是一种静态类型的语言。如果您无法将 JSON 更改为更清洁的东西,这里展示了您如何选择使用 Any
的动态行为。
//: Playground - noun: a place where people can play
import PlaygroundSupport
import UIKit
let json = """
{
"name": "John Doe",
"details": [{
"name": "exampleString"
}, {
"name": [1, 2, 3]
}]
}
"""
struct Detail {
var name: Any?
var nameString: String? {
return name as? String
}
var nameIntArray: [Int]? {
return name as? [Int]
}
enum CodingKeys: CodingKey {
case name
}
}
extension Detail: Encodable {
func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
if let string = name as? String {
try container.encode(string, forKey: .name)
}
if let array = name as? [Int] {
try container.encode(array, forKey: .name)
}
}
}
extension Detail: Decodable {
init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
if let string = try? values.decode(String.self, forKey: .name) {
name = string
} else if let array = try? values.decode(Array<Int>.self, forKey: .name) {
name = array
}
}
}
struct Record: Codable {
var name: String
var details: [Detail]
}
let jsonDecoder = JSONDecoder()
let record = try! jsonDecoder.decode(Record.self, from: json.data(using: .utf8)!)
print("\(record.details.first!.name!) is of type: \(type(of:record.details.first!.name!))")
print("\(record.details.last!.name!) is of type: \(type(of:record.details.last!.name!))")
输出是:
exampleString is of type: String
[1, 2, 3] is of type: Array<Int>
API 发给我这个 json :
{
"name": "John Doe",
"details": [{
"name": "exampleString"
}, {
"name": [1, 2, 3]
}]
}
这里的问题是细节数组有两个不同值类型的字典。 如何使用 swift4 的可解码协议在模型中解码这个 json ?
我不建议您使用异构类型构建 JSOn;在这种情况下 details.name 可以是字符串或 Int 数组。虽然你可以做到这一点 Swift,但它有点混乱,因为它默认是一种静态类型的语言。如果您无法将 JSON 更改为更清洁的东西,这里展示了您如何选择使用 Any
的动态行为。
//: Playground - noun: a place where people can play
import PlaygroundSupport
import UIKit
let json = """
{
"name": "John Doe",
"details": [{
"name": "exampleString"
}, {
"name": [1, 2, 3]
}]
}
"""
struct Detail {
var name: Any?
var nameString: String? {
return name as? String
}
var nameIntArray: [Int]? {
return name as? [Int]
}
enum CodingKeys: CodingKey {
case name
}
}
extension Detail: Encodable {
func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
if let string = name as? String {
try container.encode(string, forKey: .name)
}
if let array = name as? [Int] {
try container.encode(array, forKey: .name)
}
}
}
extension Detail: Decodable {
init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
if let string = try? values.decode(String.self, forKey: .name) {
name = string
} else if let array = try? values.decode(Array<Int>.self, forKey: .name) {
name = array
}
}
}
struct Record: Codable {
var name: String
var details: [Detail]
}
let jsonDecoder = JSONDecoder()
let record = try! jsonDecoder.decode(Record.self, from: json.data(using: .utf8)!)
print("\(record.details.first!.name!) is of type: \(type(of:record.details.first!.name!))")
print("\(record.details.last!.name!) is of type: \(type(of:record.details.last!.name!))")
输出是:
exampleString is of type: String
[1, 2, 3] is of type: Array<Int>