61 lines
1.5 KiB
Swift
61 lines
1.5 KiB
Swift
//
|
||
// APIEnvelope.swift
|
||
// suixinkan
|
||
//
|
||
|
||
import Foundation
|
||
|
||
/// 后端统一响应包裹实体,承载业务 code、msg 和真实 data。
|
||
struct APIEnvelope<T: Decodable>: Decodable {
|
||
let data: T?
|
||
let code: Int
|
||
let msg: String?
|
||
|
||
/// 判断后端业务 code 是否代表成功。
|
||
var isSuccess: Bool {
|
||
code == 100000
|
||
}
|
||
|
||
/// 后端统一 Envelope 的 JSON 字段映射。
|
||
enum CodingKeys: String, CodingKey {
|
||
case data
|
||
case code
|
||
case msg
|
||
}
|
||
|
||
/// 自定义解码逻辑,兼容成功响应、空 data 和 EmptyPayload。
|
||
init(from decoder: Decoder) throws {
|
||
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||
code = try container.decodeIfPresent(Int.self, forKey: .code) ?? 0
|
||
msg = try container.decodeIfPresent(String.self, forKey: .msg)
|
||
|
||
guard code == 100000 else {
|
||
data = nil
|
||
return
|
||
}
|
||
|
||
guard container.contains(.data), try !container.decodeNil(forKey: .data) else {
|
||
data = nil
|
||
return
|
||
}
|
||
|
||
if T.self == EmptyPayload.self {
|
||
data = EmptyPayload() as? T
|
||
return
|
||
}
|
||
|
||
data = try container.decode(T.self, forKey: .data)
|
||
}
|
||
}
|
||
|
||
/// 空响应实体,用于表示接口成功但不返回业务 data。
|
||
struct EmptyPayload: Codable {}
|
||
|
||
/// 错误响应实体,用于从 HTTP 错误体中提取服务端文案。
|
||
struct ErrorEnvelope: Decodable {
|
||
let code: Int?
|
||
let msg: String?
|
||
let message: String?
|
||
let error: String?
|
||
}
|