简体   繁体   English

在Argo中解码泛型类型

[英]Decoding a generic type in Argo

I'm using Thoughtbot's Argo framework for parsing JSON objects into models. 我正在使用Thoughtbot的Argo框架将JSON对象解析为模型。

I'm running into an issue where I have a protocol and its extension like so 我遇到了一个问题,我有一个协议及其扩展,如此

protocol SomeProtocol {
    associatedtype Model
    func foo()     
}

extension SomeProtocol where Model: Decodable {
    func foo() -> Model? {
        // someJSON is AnyObject in this case, say, from a network call
        guard let model: Model = decode(someJSON) else { return nil }
        return model
    }
}

and the class that conforms to this protocol looks something like this 并且符合此协议的类看起来像这样

class SomeClass: SomeProtocol {
    typealias Model = ArgoModel

    func bar() {
        print(foo())
    }
}

and the model like this 和这样的模型

struct ArgoModel {
    let id: String
}

extension ArgoModel: Decodable {
    static func decode(j: AnyObject) -> Decoded<ArgoModel> {
        return curry(self.init)
            <^> j <| "id"
    }
}

(I'm also using their Curry library as well to curry the init method) (我也在使用他们的Curry库来讨论init方法)

The problem I'm having is that, in the SomeProtocol extension, the associatedtype, Model, can't be decoded by Argo. 我遇到的问题是,在SomeProtocol扩展中,关联类型Model不能被Argo解码。 The error I get is 我得到的错误是

No 'decode' candidates produced the expected contextual result type 'Self.Model?'

Is this a limitation of the Swift type system? 这是Swift类型系统的限制吗? Or is there something I'm missing? 还是有什么我想念的?

After researching some more it seems like this is a limitation of the Swift type system as of Swift 2.3. 在研究了一些之后,似乎这是Swift类型系统的限制,如Swift 2.3。 The exact reason for the issue is that contextual types such as collections and monads can't conform to Decodable in Argo. 问题的确切原因是诸如集合和monad之类的上下文类型不能符合Argo中的Decodable。 So my models would work as long as they were not contained in a collection. 所以我的模型只要不包含在集合中就可以工作。 With Swift 3.0, the goal is to allow 使用Swift 3.0,目标是允许

the ability to make a constrained extension conform to a new protocol (ie, an array of Equatable elements is Equatable) 使受约束的扩展符合新协议的能力(即,Equatable元素的数组是Equatable)

as seen in this issue: https://github.com/thoughtbot/Argo/issues/334 如本期所述: https//github.com/thoughtbot/Argo/issues/334

My current workaround is to make a plural model which contains the array of models and decode that in the SomeProtocol extension. 我目前的解决方法是使其中包含的车型阵列复数模型,并进行解码在SomeProtocol扩展。 So now my model would look like this: 所以现在我的模型看起来像这样:

struct ArgoModels {
    let models: [ArgoModel]
}

extension ArgoModels: Decodable {
    static func decode(j: JSON) -> Decoded<ArgoModels> {
        switch j {
            case .Array(let a):
                return curry(self.init) <^> sequence(a.map(ArgoModel.decode))
            default:
                return .typeMismatch("Array", actual: j)
        }
    }
}

struct ArgoModel {
    let id: String
}

extension ArgoModel: Decodable {
    static func decode(j: AnyObject) -> Decoded<ArgoModel> {
        return curry(self.init)
            <^> j <| "id"
    }
}

Then in the implementing class, I can make a typealias, Model that can either be a single object or a collection of them in a generic way. 然后在实现类中,我可以创建一个typealias,Model可以是一个对象,也可以是通用方式的集合。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM