无法将类型“Codable”(又名“Decodable & Encodable”)的值转换为预期参数类型“T.Type”

Joe*_*tto 6 generics xcode json swift swift5

我正在开发一个处理 JSON 解析的小结构。到目前为止,一切正常,除了我想传递一个自定义结构作为用于解码的结构,JSONDecoder().decode(type.self, from: data)但这会引发以下错误:

无法将类型“Codable”(又名“Decodable & Encodable”)的值转换为预期参数类型“T.Type”

private func parseJson(data: Data, type: Codable) -> Codable? {
    do {
        let decoded = try JSONDecoder().decode(type.self, from: data)
        
        return decoded
    } catch {
        print("JSON decode error: \(error.localizedDescription)")
    }
    
    return nil
}
Run Code Online (Sandbox Code Playgroud)

有没有一种方法可以将结构传递到此方法中以用作函数的类型decode()?如果我直接设置我试图传递到decode()函数上的函数的类型,代码将按预期工作,只有当我尝试传递它时才会出错。

Leo*_*bus 6

您需要的是一个通用方法:

private func parseJson<T: Decodable>(data: Data, type: T.Type) -> T? {
    do {
        return try JSONDecoder().decode(type.self, from: data)
    } catch {
        print("JSON decode error:", error)
        return nil
    }
}
Run Code Online (Sandbox Code Playgroud)

您还可以省略类型并显式设置结果对象的类型:

private func parseJson<T: Decodable>(data: Data) -> T? {
    do {
        return try JSONDecoder().decode(T.self, from: data)
    } catch {
        print("JSON decode error:", error)
        return nil
    }
}
Run Code Online (Sandbox Code Playgroud)

游乐场测试:

struct User: Codable {
    let id: Int
    let name: String
}
let user: User = .init(id: 2, name: "abc")
let userData = try! JSONEncoder().encode(user)

let decodedUser: User = parseJson(data: userData)!
decodedUser.name  // "abc"
Run Code Online (Sandbox Code Playgroud)

注意:我返回可选类型,但你绝对应该让你的方法抛出并返回非可选类型,正如你在下面我扩展数据的地方所看到的:

extension Data {
    func decodedObject<T: Decodable>() throws -> T {
        try JSONDecoder().decode(T.self, from: self)
    }
}
Run Code Online (Sandbox Code Playgroud)
do {
    let decodedUser: User = try userData.decodedObject()
    print(decodedUser.name)  // "abc"
} catch {
    print(error)
}
Run Code Online (Sandbox Code Playgroud)

  • “可编码”不是一种类型,而是一种协议。`T` 是一个泛型类型,需要符合 `Decodable` (3认同)