Swift通用可串行化协议

Swift通用可串行化协议,swift,generics,swift-protocols,Swift,Generics,Swift Protocols,我注意到我有很多重复的代码来获取/发送JSON到我的应用程序的API,但唯一不同的是反序列化的实体是什么。因此,为了简洁起见,我提出了以下设计,即GET方法: HTTPClient.swift func getEntityJSON<T: JSONSerializable>( type: T.Type, url: String, completionHandler: @escaping (_ result: T?,

我注意到我有很多重复的代码来获取/发送JSON到我的应用程序的API,但唯一不同的是反序列化的实体是什么。因此,为了简洁起见,我提出了以下设计,即GET方法:

HTTPClient.swift

func getEntityJSON<T: JSONSerializable>(
    type: T.Type,
    url: String,
    completionHandler: @escaping (_ result: T?,
                                  _ headers: [String: String]?,
                                  _ statusCode: Int?,
                                  _ error: Error?) -> Void) {
    HttpClient.sharedInstance().getJSON(url, completionHandler: { (jsonData, headers, statusCode, error) in
        if let error = error {
            completionHandler(nil, headers, statusCode, error)
        } else {
            if let entityData = jsonData {
                completionHandler(T.fromJSON(data: entityData), headers, statusCode, nil)
            }
        }
    })
}
以下是JSONSerializable协议:

import Foundation
import SwiftyJSON


protocol Serializable: Codable {
    static func deserialize<T: Codable>(data: Data) -> T?
    func serialize() -> Data?
}

extension Serializable {
    static func deserialize<T: Decodable>(data: Data) -> T? {
        let decoder = JSONDecoder()
        decoder.keyDecodingStrategy = .convertFromSnakeCase
        decoder.dateDecodingStrategy = .formatted(DateFormatter.iso8601Full)
        return try? decoder.decode(T.self, from: data)
    }
    
    func serialize() -> Data? {
        let encoder = JSONEncoder()
        encoder.keyEncodingStrategy = .convertToSnakeCase
        encoder.dateEncodingStrategy = .formatted(DateFormatter.iso8601Full)
        return try? encoder.encode(self)
    }
}

protocol JSONSerializable: Serializable {
    func toJSON() -> JSON?
    static func fromJSON<T>(data: JSON) -> T?
}


extension JSONSerializable {
    func toJSON() -> JSON? {
        if let data = self.serialize() {
            return try? JSON(data: data)
        } else {
            return nil
        }
    }
}
我将得到序列化、反序列化的toJSON函数。但编译器抱怨翻译不符合JSONSerializable,因为缺少:

来自JSONDATA的静态函数:JSON->T?。我想我可以用一个具体的类型来实现这个功能,在本例中是翻译

我希望能够同时翻译.fromJSONdata:data和T.fromJSONdata:data。如何实现这一点?

泛型意味着您的方法可以处理调用者、被调用者、实现者或其他任何人指定的任何类型。就fromJSON而言,情况显然并非如此。fromJSON的任何具体实现都只能在T作为封闭类型时工作,因此fromJSON不适合作为泛型

当一个方法只在T是封闭类型的情况下工作时,它是自类型的用例:

这样,您的翻译实现将符合协议

同样,反序列化也应声明为:

static func deserialize(data: Data) -> Self?
如果您确实想要一个JSONSerialisable,它可以将JSON转换为调用者想要的任何类型,那么它就不是一个JSONSerialisable,而是一个JSONSerialiser,在这种情况下,从Codable继承没有多大意义。

泛型意味着您的方法可以处理调用者而不是被调用者想要的任何类型,不是实现者,也不是其他任何人指定的。就fromJSON而言,情况显然并非如此。fromJSON的任何具体实现都只能在T作为封闭类型时工作,因此fromJSON不适合作为泛型

当一个方法只在T是封闭类型的情况下工作时,它是自类型的用例:

这样,您的翻译实现将符合协议

同样,反序列化也应声明为:

static func deserialize(data: Data) -> Self?

如果您确实想要一个JSONSerialisable,它可以将JSON转换为调用者想要的任何类型,那么它就不是一个JSONSerialisable,而是一个JSONSerialiser,在这种情况下从Codable继承没有多大意义。

好的,我最终实现了一个JSONSerializer,因为我无法让它对要反序列化的项集合起作用。这就是它目前的样子:

import Foundation
import SwiftyJSON


protocol JSONSerializable {
    static func fromJSON(data: JSON) -> Self?
}


class JSONSerializer {
    static func deserialize<T: Decodable>(_ type: T.Type, data: Data) -> T? {
        let decoder = JSONDecoder()
        decoder.keyDecodingStrategy = .convertFromSnakeCase
        decoder.dateDecodingStrategy = .formatted(DateFormatter.iso8601Full)
        return try? decoder.decode(type, from: data)
    }
    
    static func serialize<T: Encodable>(_ object: T) -> Data? {
        let encoder = JSONEncoder()
        encoder.keyEncodingStrategy = .convertToSnakeCase
        encoder.dateEncodingStrategy = .formatted(DateFormatter.iso8601Full)
        return try? encoder.encode(object)
    }
    
    static func fromJSON<T: JSONSerializable>(type: T.Type, data: JSON) -> T? {
        T.fromJSON(data: data)
    }
    
    static func toJSON<T: Encodable>(_ object: T) -> JSON? {
        if let data = Self.serialize(object) {
            return try? JSON(data: data)
        } else {
            return nil
        }
    }
}

好的,我最终实现了一个JSONSerializer,因为我无法让它对要反序列化的项集合起作用。这就是它目前的样子:

import Foundation
import SwiftyJSON


protocol JSONSerializable {
    static func fromJSON(data: JSON) -> Self?
}


class JSONSerializer {
    static func deserialize<T: Decodable>(_ type: T.Type, data: Data) -> T? {
        let decoder = JSONDecoder()
        decoder.keyDecodingStrategy = .convertFromSnakeCase
        decoder.dateDecodingStrategy = .formatted(DateFormatter.iso8601Full)
        return try? decoder.decode(type, from: data)
    }
    
    static func serialize<T: Encodable>(_ object: T) -> Data? {
        let encoder = JSONEncoder()
        encoder.keyEncodingStrategy = .convertToSnakeCase
        encoder.dateEncodingStrategy = .formatted(DateFormatter.iso8601Full)
        return try? encoder.encode(object)
    }
    
    static func fromJSON<T: JSONSerializable>(type: T.Type, data: JSON) -> T? {
        T.fromJSON(data: data)
    }
    
    static func toJSON<T: Encodable>(_ object: T) -> JSON? {
        if let data = Self.serialize(object) {
            return try? JSON(data: data)
        } else {
            return nil
        }
    }
}

感谢您的回答,以及关于如何处理此问题的解释和建议。我想我需要一段时间才能对泛型有一个很好的理解。谢谢你的解释和建议。我想我需要一段时间才能很好地理解泛型。
import Foundation
import SwiftyJSON


protocol JSONSerializable {
    static func fromJSON(data: JSON) -> Self?
}


class JSONSerializer {
    static func deserialize<T: Decodable>(_ type: T.Type, data: Data) -> T? {
        let decoder = JSONDecoder()
        decoder.keyDecodingStrategy = .convertFromSnakeCase
        decoder.dateDecodingStrategy = .formatted(DateFormatter.iso8601Full)
        return try? decoder.decode(type, from: data)
    }
    
    static func serialize<T: Encodable>(_ object: T) -> Data? {
        let encoder = JSONEncoder()
        encoder.keyEncodingStrategy = .convertToSnakeCase
        encoder.dateEncodingStrategy = .formatted(DateFormatter.iso8601Full)
        return try? encoder.encode(object)
    }
    
    static func fromJSON<T: JSONSerializable>(type: T.Type, data: JSON) -> T? {
        T.fromJSON(data: data)
    }
    
    static func toJSON<T: Encodable>(_ object: T) -> JSON? {
        if let data = Self.serialize(object) {
            return try? JSON(data: data)
        } else {
            return nil
        }
    }
}
    static func fromJSON<T: Decodable>(type: T.Type, data: JSON) -> T? {
        if let jsonData = try? data.rawData() {
            return Self.deserialize(type, data: jsonData)
        }
        return nil
    }