我有一个通用的REST请求:
struct Request<T> {…}
T
是请求的返回类型,例如:
struct Animal {…}
let animalRequest = Request<Animal>
let animal: Animal = sendRequest(animalRequest)
现在我想表示泛型类型必须符合Decodable
,以便我可以解码来自服务器的JSON响应:
struct Request<T> where T: Decodable {…}
struct Animal: Decodable {…}
这是有道理的,也是有效的 - 直到我得到一个没有回应的请求,Request<Void>
。编译器对此不满意:
Type 'Void' does not conform to protocol 'Decodable'
编译器很快找到了我通过向Decodable
添加Void
一致性来解决此问题的错误尝试:
extension Void: Decodable {…} // Error: Non-nominal type 'Void' cannot be extended
将请求通用于返回类型是正确的。有没有办法让它与Void
返回类型一起使用? (例如,只在服务器上创建内容并且不返回任何内容的请求。)
答案 0 :(得分:15)
一个简单的解决方法是引入一个替换Void
的自定义“无回复”类型:
struct NoReply: Decodable {}
可以使Void
符合Decodable
。 Void
只是空元组()
的类型别名,而元组此时无法符合协议,但最终将会符合协议。
答案 1 :(得分:0)
我发现有时可以将其他类型的其他编码对象解码为NoReply.self。例如,自定义错误类型(枚举)可以是。
这种情况的操场示例:
arr = [("cluster_comp_444", "Home equipment & interior design"), \
("cluster_comp_1160", "Going Out & shows"), \
("cluster_comp_217576624", "Healthcare & medicine"), \
("cluster_comp_465", "Good deals")]
df = spark.createDtaFrame(arr)
dic = {row[0]:row[1] for row in df.collect()}
所以我的建议是为NoReply添加唯一性(zoul的答案):
enum MyError: String, Codable {
case general
}
let voidInstance = VoidResult()
let errorInstance = MyError.general
let data1 = try! JSONEncoder().encode(voidInstance)
let data2 = try! JSONEncoder().encode(errorInstance)
let voidInstanceDecoded = try! JSONDecoder().decode(VoidResult.self, from: data1)
//VoidResult as expected
let errorInstanceDecoded = try! JSONDecoder().decode(MyError.self, from: data2)
//MyError.general as expected
let voidInstanceDecodedFromError = try! JSONDecoder().decode(VoidResult.self, from: data2)
//VoidResult - NOT EXPECTED
let errorInstanceDecodedFromVoid = try! JSONDecoder().decode(ScreenError.self, from: data1)
//DecodingError.typeMismatch - Expected