假設我想按如下方式解碼 Person 結構。
struct Person: Decodable {
let firstName: String
let lastName: String
let age: Int: String
}
我知道只能用上面的方法解碼資料。因此,如果上面和下面的實作之間沒有區別,我是否不將屬性更改為自定義名稱?
此外,還有其他情況要使用 CodingKeys 嗎?除了重命名目的之外,當它們是必需的時,我感到困惑。
struct Person: Decodable {
let firstName: String
let lastName: String
let age: Int: String
}
enum CodingKeys: String, CodingKey {
case firstName
case lastName
case age
}
uj5u.com熱心網友回復:
因此,如果上面和下面的實作之間沒有區別,我是否不將屬性更改為自定義名稱?
是的,但這里有一些誤解。您擁有的兩個實作實際上是相同的,因為在第二個實作中CodingKeys永遠不會使用列舉。要使用,列舉必須嵌套在Decodable符合型別中(Person在本例中):
struct Person: Decodable {
let firstName: String
let lastName: String
let age: Int
enum CodingKeys: String, CodingKey {
case firstName
case lastName
case age
}
}
實際上,此實作與您提供的實作之間沒有區別。
此外,還有其他情況要使用 CodingKeys 嗎?
CodingKeys 不僅僅被 Decodable 使用,它們也被 Encodable 使用。使用 Encodable 時,使用 CodingKeys 的一個原因是指定應序列化的實體欄位的子集。
uj5u.com熱心網友回復:
例如,您可以以不同的方式使用 CodingKeys,例如,當您知道您期望的 JSON 中至少有一個值名稱實際上與您的“let 或 var”名稱不同時。
例子:
struct Person: Decodable {
let firstName: String
let lastName: String
let age: Int: String
}
enum CodingKeys: String, CodingKey {
case firstName = "first_name"
case lastName
case age
}
另一種情況是當您使用類繼承時。
總之,如果您絕對確定您使用的變數名稱與您的編碼鍵(JSON)相同,則可以省略它(但如果您想放置它,則無所謂),但如果有區別,也許您的 codingKeys 更改為大寫或使用不同的單詞,您應該使用列舉將正確的鍵映射到變數名稱。
uj5u.com熱心網友回復:
首先,使用有一個成敗規則CodingKeys:
您可以省略
CodingKeys完全如果JSON -或任何Codable符合格式-鍵完全匹配相應的屬性(如在你的例子)或轉換由適當的覆寫keyDecodingStrategy。否則,您必須指定所有
CodingKeys需要解碼的內容(另請參閱下面的原因#3)。
使用的主要原因有以下三個CodingKeys:
- Swift 變數/屬性名稱不能以數字開頭。如果密鑰確實以數字開頭,則必須指定兼容
CodingKey才能完全解碼密鑰。 - 您想使用不同的屬性名稱。
- 您希望從解碼中排除鍵,例如
id不在 JSON 中并使用UUID常量初始化的屬性。
CodingKeys如果您實作init(from decoder解碼密鑰容器,并且是強制性的。
uj5u.com熱心網友回復:
如果您的 JSON 具有任意數量的編碼鍵(也稱為動態鍵),則 CodingKeys 會非常有用。這是一個例子。
import UIKit
// Consider JSON with infinite number of keys: "S001", "S002" and so on
let jsonData = """
{
"S001": {
"firstName": "Tony",
"lastName": "Stark"
},
"S002": {
"firstName": "Peter",
"lastName": "Parker"
},
"S003": {
"firstName": "Bruce",
"lastName": "Wayne"
}
}
""".data(using: .utf8)!
struct Student: Decodable {
let firstName: String
let lastName: String
}
struct DecodedArray: Decodable {
var array: [Student]
// Define DynamicCodingKeys type needed for creating
// decoding container from JSONDecoder
private struct DynamicCodingKeys: CodingKey {
// Use for string-keyed dictionary
var stringValue: String
init?(stringValue: String) {
self.stringValue = stringValue
}
// Use for integer-keyed dictionary
var intValue: Int?
init?(intValue: Int) {
// We are not using this, thus just return nil
return nil
}
}
init(from decoder: Decoder) throws {
// 1
// Create a decoding container using DynamicCodingKeys
// The container will contain all the JSON first level key
let container = try decoder.container(keyedBy: DynamicCodingKeys.self)
var tempArray = [Student]()
// 2
// Loop through each key (student ID) in container
for key in container.allKeys {
// Decode Student using key & keep decoded Student object in tempArray
let decodedObject = try container.decode(Student.self, forKey: DynamicCodingKeys(stringValue: key.stringValue)!)
tempArray.append(decodedObject)
}
// 3
// Finish decoding all Student objects. Thus assign tempArray to array.
array = tempArray
}
}
let decodedResult = try! JSONDecoder().decode(DecodedArray.self, from: jsonData)
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/345145.html
