Swift 4 JSONDecoder 解码协议类型

Posted

技术标签:

【中文标题】Swift 4 JSONDecoder 解码协议类型【英文标题】:Swift 4 JSONDecoder decode a protocol type 【发布时间】:2017-10-14 03:20:11 【问题描述】:

以下代码无法编译:

public protocol Foo: Decodable 
  var message: String  get 

struct Bar: Foo 
  let message: String


// the type conforming Foo protocol is passed from somewhere
let type: Foo.Type = Bar.self
decode(type: type, from: Data())

func decode<T>(type: T.Type, from data: Data) Where T: Decodable 
  let decoder = JSONDecoder()
  try! decoder.decode(type, from: data)

它抛出错误: Cannot invoke 'decode' with an argument list of type '(Foo.Type, from: Data)'

你们有什么想法吗?

【问题讨论】:

我需要像这样将参数约束到协议中:func decode&lt;T: Foo&gt;(type: T, from data: Data) let decoder = JSONDecoder() try! decoder.decode(type, from: data) @3stud1ant3 decode(type: Bar.self, from: data) throws Cannot invoke 'decode' with an argument list of type '(T, from: Data)' JSONEncoder / JSONDecoder 期望具体类型,您不能使用协议类型。 比较***.com/q/44441223/2976878 @akabc 你找到解决方案了吗? 【参考方案1】:

你可以这样使用:

public protocol Foo: Decodable 
    var message: String  get 

struct Bar: Foo 
    let message: String


class ViewController: UIViewController 
    let bar = """
        "message": "Sample message"
    """

    override func viewDidLoad() 
        super.viewDidLoad()
        let type = Bar.self
        decode(type: type, from: bar.data(using: .utf8)!)
    

    func decode<Foo>(type: Foo.Type, from data: Data) where Foo: Decodable 
        let decoder = JSONDecoder()
        let parsedData = try! decoder.decode(type, from: data)
        print(parsedData)
    

【讨论】:

如何编译? let type: Foo.Type = Bar.self decode(type: type, from: bar.data(using: .utf8)!),是因为type是从某个地方传过来的,具体类型未知,我只知道符合Foo 您有什么问题吗?【参考方案2】:

您应该在您的Bar 上使用Codable 来代替:

protocol Foo 
    var message: String  get 

struct Bar: Foo, Codable 
    let message: String

用法:

let bar = Bar(message: "Just a message")
if let data = try? JSONEncoder().encode(bar) 
    print(String(data:data, encoding:.utf8) ?? "") // "message":"Just a message"\n"// lets decode it
    if let decodedBar = try? JSONDecoder().decode(Bar.self, from: data) 
        print(decodedBar.message) //"Just a message\n"
     

【讨论】:

我希望从某处传递 decode(type) 的参数 你为什么想要那个?只需在要解码的任何地方使用使用代码即可。 我想要Bar.self可以传递给这个函数func decode(type: Foo.Type, from data: Data)

以上是关于Swift 4 JSONDecoder 解码协议类型的主要内容,如果未能解决你的问题,请参考以下文章

如何在 swift 4.1 和 xcode 9.3 中使用 JSONDecoder 解码嵌套的 JSON 数组和对象?

Swift - 将类型动态传递给 JSONDecoder

iOS - JSONEncoder和JSONDecoder介绍

如何在 swift 4 中使用 JSONDecoder 从嵌套 JSON 中获取数据?

在 Swift 4 中使用新的 JSONDecoder 协议时,我得到“无法读取数据,因为它的格式不正确。”错误

使用 JSONDecoder 解码 [[String]]?