【问题标题】:Implement CodingKey mapping in super class在超类中实现 CodingKey 映射
【发布时间】:2019-09-12 17:01:49
【问题描述】:

我有一个结构,它具有一些属性、一个 CodingKey 枚举(为了符合 Codable 协议)和一些返回映射到字符串的键数组的计算变量。

我想要做的是将这些计算变量提取到协议(如果我必须将结构更改为类,则为超类)以避免在每个结构/类中重复实现。我需要很多

问题是我找不到知道 CodingKey 枚举的方法。

编辑: 数据库实体

/// 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 { $0.rawValue }
    static var columnsJoined: String = columns.joined(separator: String.commaSpace)
    static var columnsTableName: [String] = columns.map { tableName + String.dot + $0 }
    static var columnsJoinedTableName: String = columnsTableName.joined(separator: String.commaSpace)
}

编辑

使用 Sweeper 回答中的给定代码,我试图在新结构中实现协议,但编译器要求将类型设置为 typealias CodingKeyType(因为定义的协议具有关联类型)。

public protocol Table {
    associatedtype ColumnKeysType: (CodingKey & CaseIterable & RawRepresentable)
    static var tablename: String { get }
}

这里是要测试的结构:

struct AccountsTest: Table {

    typealias CodingKeyType = <#type#>
}

我尝试创建另一个结构,以便将类型分配给类型别名,但是我缺少/做错了一些事情(我必须实现这个变量、构造函数和类型别名)。

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

有什么技巧可以完成这项工作吗?

谢谢

【问题讨论】:

  • 那么 DBEntity 是什么?
  • @matt(后编辑)DBEntity 是与数据库表直接相关的任何对象的协议。

标签: swift struct swift-protocols


【解决方案1】:

请注意,您尝试提取的属性不是计算属性。

你要提取的属性似乎只依赖于tableNameCodingKeys,所以我们可以这样写一个协议:

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 { $0.rawValue } }
    static var columnsJoined: String { return columns.joined(separator: " ") }
    static var columnsTableName: [String] { return columns.map { tableName + "." + $0 } }
    static var columnsJoinedTableName: String { return columnsTableName.joined(separator: " ") }
}

【讨论】:

  • 你完全正确,我对计算属性的理解是错误的(真是个错误)。非常感谢您的回答!这正是我想要的!你摇滚!
  • 我已编辑原始帖子以添加显示错误的新代码。我找不到要设置为 typealias CodingKeyType 的类型...
  • @JavierFernandezMartínez 您应该将 CodingKeys 枚举作为类型别名。无需创建新类型。
  • 我已经尝试过:typealias ColumnKeysType = CodingKeys 但编译器继续显示错误。我现在的错误是我不小心从 CodingKeys 枚举中删除了 CodingKey、CaseIterable 协议。现在正在按预期工作。再次感谢您!
【解决方案2】:

您不需要自己进行转换。您可以使用decoder.keyDecodingStrategy = .convertFromSnakeCase,您的 json 将映射到您的骆驼案例属性。

更多信息:

https://developer.apple.com/documentation/foundation/jsondecoder/keydecodingstrategy/convertfromsnakecase

【讨论】:

  • 感谢您的回答!我曾尝试使用 keyDecodingStrategy 但(不幸的是)某些键不符合完全蛇盒命名。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-03-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多