每个API都有三个参数作为响应。
我已经创建了基本模型。
struct ResponseBase<T:Codable> : Codable {
let code : String?
let data : [T]
let message : String?
enum CodingKeys: String, CodingKey {
case code = "Code"
case data = "Data"
case message = "Message"
}
init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
code = try values.decodeIfPresent(String.self, forKey: .code)
data = try values.decodeIfPresent([T].self, forKey: .data)
message = try values.decodeIfPresent(String.self, forKey: .message)
}
}
struct SocialWarmer : Codable {
let createdDate : String?
let lookUpId : String?
let lookupKey : String?
let lookupValue : String?
let parentId : String?
let statusFlag : String?
let type : String?
let updatedDate : String?
enum CodingKeys: String, CodingKey {
case createdDate = "CreatedDate"
case lookUpId = "LookUpId"
case lookupKey = "LookupKey"
case lookupValue = "LookupValue"
case parentId = "ParentId"
case statusFlag = "StatusFlag"
case type = "Type"
case updatedDate = "UpdatedDate"
}
init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
createdDate = try values.decodeIfPresent(String.self, forKey: .createdDate)
lookUpId = try values.decodeIfPresent(String.self, forKey: .lookUpId)
lookupKey = try values.decodeIfPresent(String.self, forKey: .lookupKey)
lookupValue = try values.decodeIfPresent(String.self, forKey: .lookupValue)
parentId = try values.decodeIfPresent(String.self, forKey: .parentId)
statusFlag = try values.decodeIfPresent(String.self, forKey: .statusFlag)
type = try values.decodeIfPresent(String.self, forKey: .type)
updatedDate = try values.decodeIfPresent(String.self, forKey: .updatedDate)
}
}
以下是API请求的代码。
class BaseApiClient {
static let `default` = BaseApiClient()
private init() {
}
func fetch<model:Codable>(request:APIRouter,decoder : JSONDecoder = JSONDecoder() ,onSuccess: @escaping ([model]) -> Void) {
if Connectivity.isReachable {
(UIApplication.shared.delegate as! AppDelegate).addProgressView()
Alamofire.request(request).responseJSON { (response) in
switch response.result {
case .success( let apiResponse) :
DispatchQueue.main.async {
(UIApplication.shared.delegate as! AppDelegate).hideProgrssVoew()
}
if let responseData = apiResponse as? [String:Any] , let status = responseData["Code"] as? String , status == "SUCCESS" {
do {
let responseModel = try decoder.decode(ResponseBase<model>.self, from: response.data!)
onSuccess(responseModel.data!)
}
catch let error as NSError {
print("failed reason : \(error.localizedDescription)")
}
print(model.Type.self)
print(model.self)
}
else {
UIApplication.shared.gettopMostViewController()?.presentAlerterror(title: "Erorr", message: "Service not Avilabel" ,okclick: nil)
}
case .failure(let error) :
UIApplication.shared.gettopMostViewController()?.presentAlerterror(title: "Erorr", message: error.localizedDescription, okclick: nil)
}
}
}
else {
(UIApplication.shared.delegate as! AppDelegate).hideProgrssVoew()
UIApplication.shared.gettopMostViewController()?.presentAlerterror(title: "Error", message: "connnection not avilabel", okclick: nil)
}
}
}
以下是用于调用API的代码。
BaseApiClient.default.fetch(request: APIRouter.GetSocialWarmerType) { (response: [SocialWarmer]) in
print(response)
}
,但是如果Data是单个对象,则此模型和API方法将不起作用。 我试图实现的目标是创建单个模型并在API方法中进行适当的更改,以解析对象数组和单个对象。
答案 0 :(得分:2)
最后,我找到了一种解决方法。我创建了两个基类,一个用于对象数组,一个用于单个对象。
Name
以下是Api方法的代码。
struct ResponseBaseArray<T:Codable> : Codable {
let code : String?
let data : [T]?
let message : String?
enum CodingKeys: String, CodingKey {
case code = "Code"
case data = "Data"
case message = "Message"
}
init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
code = try values.decodeIfPresent(String.self, forKey: .code)
data = try values.decodeIfPresent([T].self, forKey: .data)
message = try values.decodeIfPresent(String.self, forKey: .message)
}
}
struct ResponseBaseObject<T:Codable> : Codable {
let code : String?
let data : T?
let message : String?
enum CodingKeys: String, CodingKey {
case code = "Code"
case data = "Data"
case message = "Message"
}
init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
code = try values.decodeIfPresent(String.self, forKey: .code)
data = try values.decodeIfPresent(T.self, forKey: .data)
message = try values.decodeIfPresent(String.self, forKey: .message)
}
}
以下是呼叫Api的代码。
class BaseApiClient {
static let `default` = BaseApiClient()
private init() {
}
func fetch<model:Codable>(request:APIRouter , decoder: JSONDecoder = JSONDecoder() ,onSuccess: @escaping (model) -> Void) {
if Connectivity.isReachable {
(UIApplication.shared.delegate as! AppDelegate).addProgressView()
Alamofire.request(request).responseJSON { (response) in
switch response.result {
case .success( let apiResponse) :
DispatchQueue.main.async {
(UIApplication.shared.delegate as! AppDelegate).hideProgrssVoew()
}
if let responseData = apiResponse as? [String:Any] , let status = responseData["Code"] as? String , status == "SUCCESS" {
do {
let responseModel = try decoder.decode(model.self, from: response.data!)
onSuccess(responseModel)
}
catch let error as NSError {
print("failed reason : \(error.localizedDescription)")
}
}
else {
UIApplication.shared.gettopMostViewController()?.presentAlerterror(title: "Erorr", message: "Service not Avilabel" ,okclick: nil)
}
case .failure(let error) :
UIApplication.shared.gettopMostViewController()?.presentAlerterror(title: "Erorr", message: error.localizedDescription, okclick: nil)
}
}
}
else {
(UIApplication.shared.delegate as! AppDelegate).hideProgrssVoew()
UIApplication.shared.gettopMostViewController()?.presentAlerterror(title: "Error", message: "connnection not avilabel", okclick: nil)
}
}
}
如果您的Api返回单个对象而不是使用ResponseBaseObject。
BaseApiClient.default.fetch(request: APIRouter.GetSocialWarmerType) { (rsult:ResponseBaseArray<[SocialWarmer]>) in
print(rsult.data)
}
但是仍然只有当您已经知道Api将返回单个对象或对象数组时,此解决方案才有效。
答案 1 :(得分:1)
您的响应对象应仅使用T
,而不是[T]
:
struct ResponseObject<T: Decodable>: Decodable {
let code: String
let data: T?
let message: String?
enum CodingKeys: String, CodingKey {
case code = "Code"
case data = "Data"
case message = "Message"
}
}
然后,当您指定通用类型时,即在其中指定它是单个实例还是数组。
例如,当解码单个实例时,它是:
let responseObject = try JSONDecoder().decode(ResponseObject<Foo>.self, from: data)
let foo = responseObject.data
但是对于数组,它是:
let responseObject = try JSONDecoder().decode(ResponseObject<[Foo]>.self, from: data)
let array = responseObject.data
这是一个示例游乐场:
struct ResponseObject<T: Decodable>: Decodable {
let code: String?
let data: T
let message: String?
enum CodingKeys: String, CodingKey {
case code = "Code"
case data = "Data"
case message = "Message"
}
}
struct Foo: Codable {
let value: Int
}
do {
let data = """
{
"Code": "some code",
"Message": "some message",
"Data": {
"value": 42
}
}
""".data(using: .utf8)!
let responseObject = try JSONDecoder().decode(ResponseObject<Foo>.self, from: data)
let foo = responseObject.data
print(foo)
} catch {
print(error)
}
do {
let data = """
{
"Code": "some code",
"Message": "some message",
"Data": [
{
"value": 1
}, {
"value": 2
}, {
"value": 3
}
]
}
""".data(using: .utf8)!
let responseObject = try JSONDecoder().decode(ResponseObject<[Foo]>.self, from: data)
let array = responseObject.data
print(array)
} catch {
print(error)
}