swift Codable
2022-04-27 本文已影响0人
迷路的小小
unkeyedContainer
、singleValueContainer
struct Student: Codable {
let name: String
init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
name = try container.decode(String.self)
}
}
struct Classes: Codable {
let students: [Student]
init(from decoder: Decoder) throws {
var container = try decoder.unkeyedContainer()
students = try (0..<container.count!).map({ _ in try container.decode(Student.self) })
}
}
解析:
let decode = JSONDecoder()
let stuData = #"""
[
"张三",
"李四"
]
"""#.data(using: .utf8)!
do {
let student = try decode.decode(Classes.self, from: stuData)
print(student)
// Classes(students: [__lldb_expr_27.Student(name: "张三"), __lldb_expr_27.Student(name: "李四")])
} catch let err {
print(err)
}
decodeIfPresent(_:, forKey:)
、decode(_:, forKey:)
struct Student: Codable {
let sex: Int?
let name: String
let age: Int
enum Keys: String, CodingKey {
case name = "first_name"
}
init(from decoder: Decoder) throws {
let container0 = try decoder.container(keyedBy: CodingKeys.self)
sex = try container0.decodeIfPresent(Int.self, forKey: .sex)
age = try container0.decode(Int.self, forKey: .age)
let container = try decoder.container(keyedBy: Keys.self)
name = try container.decode(String.self, forKey: .name)
}
}
JSON:
let stuData = #"""
{
"first_name": "张三",
"age": 45,
"class": 3
}
"""#.data(using: .utf8)!
// Student(sex: nil, name: "张三", age: 45)
nestedUnkeyedContainer
协议:
protocol Student: Codable {
var sex: Int? { get }
var name: String { get }
var age: Int { get }
}
enum StudentKeys: String, CodingKey {
case name = "first_name"
}
struct Pupil: Student {
let sex: Int?
let name: String
let age: Int
let `class`: String
init(from decoder: Decoder) throws {
let container0 = try decoder.container(keyedBy: CodingKeys.self)
sex = try container0.decodeIfPresent(Int.self, forKey: .sex)
age = try container0.decode(Int.self, forKey: .age)
`class` = "\(try container0.decode(Int.self, forKey: .class))班"
let container = try decoder.container(keyedBy: StudentKeys.self)
name = try container.decode(String.self, forKey: .name)
}
}
struct College: Student {
let sex: Int?
let name: String
let age: Int
let year: String
init(from decoder: Decoder) throws {
let container0 = try decoder.container(keyedBy: CodingKeys.self)
sex = try container0.decodeIfPresent(Int.self, forKey: .sex)
age = try container0.decode(Int.self, forKey: .age)
year = try container0.decode(String.self, forKey: .year)
let container = try decoder.container(keyedBy: StudentKeys.self)
name = try container.decode(String.self, forKey: .name)
}
}
struct Classes: Codable {
let students: [Student]
enum CodingKeys: String, CodingKey {
case students
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
var arrContainer = try container.nestedUnkeyedContainer(forKey: .students)
let college = try arrContainer.decode(College.self)
let pupil = try arrContainer.decode(Pupil.self)
students = [college, pupil]
}
func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
var arrContainer = container.nestedUnkeyedContainer(forKey: .students)
for student in students {
if let college = student as? College {
try arrContainer.encode(college)
} else if let pupil = student as? Pupil {
try arrContainer.encode(pupil)
}
}
}
}
JSON:
{
"students":[
{
"first_name": "张三",
"age": 45,
"year": "2201级"
},
{
"first_name": "李四",
"age": 45,
"class": 3
}
]
}
Classes(students: [__lldb_expr_78.College(sex: nil, name: "张三", age: 45, year: "2201级"), __lldb_expr_78.Pupil(sex: nil, name: "李四", age: 45, class: "3班")])
nestedContainer(keyedBy:)
struct Student: Codable {
let name: String
init(from decoder: Decoder) throws {
var container = try decoder.unkeyedContainer()
let container0 = try container.nestedContainer(keyedBy: CodingKeys.self)
let container1 = try container.nestedContainer(keyedBy: CodingKeys.self)
name = try container0.decode(String.self, forKey: .name) + "_" + (try container1.decode(String.self, forKey: .name))
}
}
[
{"name": "张三"},
{"name": "李四"}
]
Student(name: "张三_李四")