在 super class 中实现 CodingKey 映射
Implement CodingKey mapping in super class
我有一个具有一些属性的结构,一个 CodingKey 枚举(为了符合 Codable 协议)和一些 returns 映射到字符串的键数组的计算变量。
我想做的是将那些计算变量提取到一个协议中(如果我必须将结构更改为 class,则为超级class)以避免重复每个 struct/class 中的实施。我需要 很多 个。
问题是我找不到知道 CodingKey 枚举的方法。
编辑:
DBentity
/// Basic protocol for any object directly related with a database table.
public protocol DBEntity: Codable, Equatable {}
代码:
///////////////////////////////////////////////////////////////////////
// MARK: - Entity Properties
struct AccountsAddresses: DBEntity {
let statusMobile: String?
let codeAccount: Int?
let codeUnitOrg: String?
let codeSalesOrg: String?
let codeAddress: Int?
let codeType: String?
let byDefault: String?
let transfered: String?
}
///////////////////////////////////////////////////////////////////////
// MARK: - Table Columns
extension AccountsAddresses {
/// Table name.
static var tableName = "ACCOUNTS_ADDRESSES"
/// Table columns keys.
enum CodingKeys: String, CodingKey, CaseIterable {
case statusMobile = "status_mobile"
case codeAccount = "code_account"
case codeUnitOrg = "code_unit_org"
case codeSalesOrg = "code_sales_org"
case codeAddress = "code_address"
case codeType = "code_type"
case byDefault = "by_default"
case transfered
}
/* This is what I'm trying to extract to a protocol(extension) or super-class. */
/// All table columns keys.
static var columns: [String] = CodingKeys.allCases.map { [=12=].rawValue }
static var columnsJoined: String = columns.joined(separator: String.commaSpace)
static var columnsTableName: [String] = columns.map { tableName + String.dot + [=12=] }
static var columnsJoinedTableName: String = columnsTableName.joined(separator: String.commaSpace)
}
编辑
使用 Sweeper 回答中的给定代码,我试图在新结构中实现协议,但编译器要求将类型设置为类型别名 CodingKeyType(因为定义的协议具有关联类型)。
public protocol Table {
associatedtype ColumnKeysType: (CodingKey & CaseIterable & RawRepresentable)
static var tablename: String { get }
}
这里是要测试的结构:
struct AccountsTest: Table {
typealias CodingKeyType = <#type#>
}
我试图创建另一个结构以便将类型分配给类型别名,但有些地方我 missing/doing 错了(我必须实现这个变量、构造函数和类型别名) .
struct Keys: (CodingKey & CaseIterable & RawRepresentable) {
var stringValue: String
var rawValue: String
var intValue: Int?
init?(stringValue: String) {}
init?(rawValue: String) {}
init?(intValue: Int) {}
typealias AllCases = Keys.RawValue
typealias RawValue = String
}
编译器继续显示错误,我找不到完成此操作的方法。
'CaseIterable' requires the types 'Keys' and 'String.Element' (aka 'Character') be equivalent
完成此操作有什么技巧吗?
谢谢
请注意,您尝试提取的属性不是计算属性。
你要提取的属性好像只依赖于tableName
和CodingKeys
,所以我们可以这样写一个协议:
protocol SomeProtocol {
associatedtype CodingKeyType : (CodingKey & CaseIterable & RawRepresentable)
static var tableName: String { get }
}
然后是这样的扩展(我已经将属性转换为计算属性):
extension SomeProtocol where CodingKeyType.RawValue == String {
static var columns: [String] { return CodingKeyType.allCases.map { [=11=].rawValue } }
static var columnsJoined: String { return columns.joined(separator: " ") }
static var columnsTableName: [String] { return columns.map { tableName + "." + [=11=] } }
static var columnsJoinedTableName: String { return columnsTableName.joined(separator: " ") }
}
您不需要自己进行转换。您可以使用 decoder.keyDecodingStrategy = .convertFromSnakeCase
,您的 json 将映射到您的驼峰式大小写属性。
更多信息:
我有一个具有一些属性的结构,一个 CodingKey 枚举(为了符合 Codable 协议)和一些 returns 映射到字符串的键数组的计算变量。
我想做的是将那些计算变量提取到一个协议中(如果我必须将结构更改为 class,则为超级class)以避免重复每个 struct/class 中的实施。我需要 很多 个。
问题是我找不到知道 CodingKey 枚举的方法。
编辑: DBentity
/// Basic protocol for any object directly related with a database table.
public protocol DBEntity: Codable, Equatable {}
代码:
///////////////////////////////////////////////////////////////////////
// MARK: - Entity Properties
struct AccountsAddresses: DBEntity {
let statusMobile: String?
let codeAccount: Int?
let codeUnitOrg: String?
let codeSalesOrg: String?
let codeAddress: Int?
let codeType: String?
let byDefault: String?
let transfered: String?
}
///////////////////////////////////////////////////////////////////////
// MARK: - Table Columns
extension AccountsAddresses {
/// Table name.
static var tableName = "ACCOUNTS_ADDRESSES"
/// Table columns keys.
enum CodingKeys: String, CodingKey, CaseIterable {
case statusMobile = "status_mobile"
case codeAccount = "code_account"
case codeUnitOrg = "code_unit_org"
case codeSalesOrg = "code_sales_org"
case codeAddress = "code_address"
case codeType = "code_type"
case byDefault = "by_default"
case transfered
}
/* This is what I'm trying to extract to a protocol(extension) or super-class. */
/// All table columns keys.
static var columns: [String] = CodingKeys.allCases.map { [=12=].rawValue }
static var columnsJoined: String = columns.joined(separator: String.commaSpace)
static var columnsTableName: [String] = columns.map { tableName + String.dot + [=12=] }
static var columnsJoinedTableName: String = columnsTableName.joined(separator: String.commaSpace)
}
编辑
使用 Sweeper 回答中的给定代码,我试图在新结构中实现协议,但编译器要求将类型设置为类型别名 CodingKeyType(因为定义的协议具有关联类型)。
public protocol Table {
associatedtype ColumnKeysType: (CodingKey & CaseIterable & RawRepresentable)
static var tablename: String { get }
}
这里是要测试的结构:
struct AccountsTest: Table {
typealias CodingKeyType = <#type#>
}
我试图创建另一个结构以便将类型分配给类型别名,但有些地方我 missing/doing 错了(我必须实现这个变量、构造函数和类型别名) .
struct Keys: (CodingKey & CaseIterable & RawRepresentable) {
var stringValue: String
var rawValue: String
var intValue: Int?
init?(stringValue: String) {}
init?(rawValue: String) {}
init?(intValue: Int) {}
typealias AllCases = Keys.RawValue
typealias RawValue = String
}
编译器继续显示错误,我找不到完成此操作的方法。
'CaseIterable' requires the types 'Keys' and 'String.Element' (aka 'Character') be equivalent
完成此操作有什么技巧吗?
谢谢
请注意,您尝试提取的属性不是计算属性。
你要提取的属性好像只依赖于tableName
和CodingKeys
,所以我们可以这样写一个协议:
protocol SomeProtocol {
associatedtype CodingKeyType : (CodingKey & CaseIterable & RawRepresentable)
static var tableName: String { get }
}
然后是这样的扩展(我已经将属性转换为计算属性):
extension SomeProtocol where CodingKeyType.RawValue == String {
static var columns: [String] { return CodingKeyType.allCases.map { [=11=].rawValue } }
static var columnsJoined: String { return columns.joined(separator: " ") }
static var columnsTableName: [String] { return columns.map { tableName + "." + [=11=] } }
static var columnsJoinedTableName: String { return columnsTableName.joined(separator: " ") }
}
您不需要自己进行转换。您可以使用 decoder.keyDecodingStrategy = .convertFromSnakeCase
,您的 json 将映射到您的驼峰式大小写属性。
更多信息: