协议扩展的可编码(或可编码)不符合它

Ash*_*lls 3 swift swift-protocols codable

我有2个协议,Filters并且Parameters都扩展了Encodable

protocol Filters: Encodable {
    var page: Int { get }
}

protocol Parameters: Encodable {
    var type: String { get }
    var filters: Filters { get }
}
Run Code Online (Sandbox Code Playgroud)

因此,我创建了符合这些协议的结构。

struct BankAccountFilters: Filters {
    var page: Int
    var isWithdrawal: Bool
}

struct BankAccountParamters: Parameters {
    let type: String = "Bank"
    var filters: Filters
}

let baf = BankAccountFilters(page: 1, isWithdrawal: true)
let bap = BankAccountParamters(filters: baf)
Run Code Online (Sandbox Code Playgroud)

失败是因为…

错误:类型“ BankAccountParamters”不符合协议“可编码”

注意:无法自动合成“可编码”,因为“过滤器”不符合“可编码”

Filters显然确实符合Encodable(至少在我看来是如此)。有没有解决的办法?

Mar*_*n R 7

协议中所述,不符合自身吗?,协议不符合其自身或其继承的协议。在你的情况,Filters不能符合Encodable

一个可能的解决方案是使struct BankAccountParamtersprotocol Parameters通用:

protocol Filters: Encodable {
    var page: Int { get }
}

protocol Parameters: Encodable {
    associatedtype T: Filters
    var type: String { get }
    var filters: T { get }
}

struct BankAccountFilters: Filters {
    var page: Int
    var isWithdrawal: Bool
}

struct BankAccountParamters<T: Filters>: Parameters {
    let type: String = "Bank"
    var filters: T
}
Run Code Online (Sandbox Code Playgroud)

现在var filters具有type T,因此符合Filters,因此也符合Encodable

这将编译并产生预期的结果:

let baf = BankAccountFilters(page: 1, isWithdrawal: true)
let bap = BankAccountParamters(filters: baf)

let data = try! JSONEncoder().encode(bap)
print(String(data: data, encoding: .utf8)!)
// {"type":"Bank","filters":{"isWithdrawal":true,"page":1}}
Run Code Online (Sandbox Code Playgroud)