如何在 Swift 4 中使用 JSONEncoder 对字典进行编码

鸡肉味*_*嘎嘣脆 6 swift codable encodable jsonencoder

我想用 JSONEncoder 将字典编码为 json。它看起来像一个请求,接收一个字典作为参数并将其编码为 json 作为 http 正文。代码如下所示:

let dict = ["name": "abcde"]

protocol Request {
    var params: [String: Encodable] { get set }
    func encode<T>(_ value: T) throws -> Data where T : Encodable
}

extension Request {
    func encode<T>(_ value: T) throws -> Data where T : Encodable {
        return try JSONEncoder().encode(value)
    }

    var body: Data? {
        if let encoded = try? self.encode(self.params) {
            return encoded
        }
        return nil
    }
}

struct BaseRequest: Request {
    var params: [String : Encodable]
}

let req = BaseRequest(params: dict)
let body = req.body
Run Code Online (Sandbox Code Playgroud)

但此代码发生错误

致命错误:Dictionary<String, Encodable> 不符合 Encodable,因为 Encodable 不符合自身。您必须使用具体类型进行编码或解码。

我怎么能让这个编码?

Tim*_*nin 3

您必须按如下方式引入类型擦除:

struct AnyEncodable: Encodable {

    let value: Encodable
    init(value: Encodable) {
        self.value = value
    }

    func encode(to encoder: Encoder) throws {
        try value.encode(to: encoder)
    }

}

struct Model: Encodable {

    var params: [String: AnyEncodable]

}

let encoder = JSONEncoder()
encoder.outputFormatting = .prettyPrinted
let json = try! encoder.encode(
    Model(
        params: [
            "hello" : AnyEncodable.init(value: "world")
        ]
    ).params
)
print(String(data: json, encoding: .utf8))
Run Code Online (Sandbox Code Playgroud)