Ninjiacoder Swift Lover, Fullstack Developer

Codable 协议

Codable 协议能实现基本的序列化和反序列化,Codable 其实是两个协议合一—— Encodable & Decodable

struct User: Codable {
	var name: String
	var age: Int
}

只需要支持 Codable 协议,现在就可以将一个 user 序列化成 JSON 数据

do {
	let user = User(name: "John", age: 31)
	let encoder = JSONEncoder()
	let data = try encoder.encode(user)
} catch {
	print(error)
}

然后我们可以通过 JSONDecoder 进行反序列化

let decoder = JSONDecoder()
let secondUser = try decoder.decode(User.self, from: data)

反序列化出来的 secondUser 应该和一开始我们定义的 user 是相同的,我们也可以看到输出序列化后的 data:

String(data: data, encoding: .utf8)!
// {"name":"John","age":31}

但是有时候我们拿到的 json 不一定和我们定义的结构一致,比如我们拿到的 User JSON 长得像这样

{
	"user_data": {
		"full_name": "John Sundell",
		"user_age": 31
	}
}

一种解决方法是,改我们的 User 结构体使得他符合该 JSON 的格式,当然这种方法优点不切实际。另一种选择我们可以扩展我们 User,添加一个专门用来做序列化和反序列化的类型:

extension User {
	struct CodingData: Codable {
		struct Container: Codable {
      var fullName: String
      var userAge: Int
    }

    var userData: Container
  }
}

然后给 User.CodingData 一个方法用来返回 User 实体

extension User.CodingData {
	var user: User {
		return User(
			name: userData.fullName,
			age: userData.userAge
		)
	}
}

但是我们“键”不一样,但是我们可以通过keyEncodingStrategykeyDecodingStrategy 来解决这个问题,设置成 convertToSnakeCase 即可

let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase

let codingData = try decoder.decoder(User.CodingData.self, from: data)
let user = codingData.user

参考文章

Codable | Swift by Sundell