这里我有一个用于api结果的结构
struct Response<Result> {
let status: Int
let message: String
let result: Result
}
现在通常使它符合Codable
意味着Result
对象需要为Codable
。这样做看起来像是以下其中之一
struct Response<Result: Codable>: Codable {...}
// or
extension Response: Codable where Result: Codable {}
我遇到的问题是某些响应没有result
键,我希望能够像使用Response
类型一样使用Void
对象而不是{ {1}}就像so question。
目前,我有一种解决方法,可以这样声明另一个Response<Void>
类型,其中没有Response
变量:
result
有没有解决的办法,这样就不必声明另一种struct BaseResponse {
let status: Int
let message: String
}
类型了?
我尝试执行以下操作,但没有任何作用
Response
符合Void
Codable
Result: Void
extension Response: Codable where Result: Codable {}
extension Response: Codable where Result: Void {}
也不起作用,因为它没有它自己的初始化程序,因此我无法使其符合Never
Codable
的{{1}}类型Nothing
所以我可以使用这样的响应
Codable
但是问题是我无法使用struct Nothing: Codable, Hashable {
init() {}
static var nothing: Nothing { return .init() }
}
类型专用的let response: Response<Nothing> = Response(
status: 200,
message: "Success",
result: .nothing
)
or
public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
self.status = try container.decode(forKey: .status)
self.message = try container.decode(forKey: .message)
// These lines don't work.
if let result = try container.decodeIfPresent(Result.self, forKey: .result) {
self.result = result
} else {
self = .nothing
}
}
方法。这么多。
答案 0 :(得分:1)
将result
设为optional
,键入 Result?
。现在,当响应包含针对result
键的值时,它将在result
属性中进行设置。否则,如果没有nil
键,它将保留为result
。
struct Response<Result: Codable>: Codable {
let status: Int
let message: String
let result: Result? //here....
}
解析这样的数据,
do {
let response = try JSONDecoder().decode(Response<String>.self, from: data)
print(response)
} catch {
print(error)
}
根据需要使用Response<String>
中想要的任何类型。
示例:
{"status":1,"message":"This is a message","result":"QWERTY"}
然后response
是Response<String>(status: 1, message: "This is a message", result: Optional("QWERTY"))
{"status":1,"message":"This is a message"}
然后response
是Response<String>(status: 1, message: "This is a message", result: nil))
答案 1 :(得分:1)
您可以这样定义init(from:)
方法:
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
status = try container.decode(Int.self, forKey: .status)
message = try container.decode(String.self, forKey: .message)
if Result.self is Nothing.Type {
result = Nothing() as! Result
} else {
result = try container.decode(Result.self, forKey: .result)
}
}
您检测到自己处于Response<Nothing>
情况,并完全跳过对结果的解码。这样,在需要结果的情况下,您可以保持常规的result
解码,并且可以使其保持非可选状态。