解析 Codable 类 并避免重复
Parse Codable classes and avoid repetition
我有一个 JSON 回复如下:
{
"http_status": 200,
"success": true,
"has_error": false,
"error": [
""
],
"response": {
"token": "",
"verified": false,
"message": ""
}
}
据我所知,对于应用程序 API 用法 http_status、成功、has_error、错误在所有 APIS 之间共享,因此我将创建一个 Codable class 来处理它,但响应可能是不同的模型,所以这就是我正在尝试做的。
我已经创建了一个通用的响应 class 如下,所以这个 class 我可以用于项目中的所有 api 以避免重复相同的 class 但名称不同:
class GeneralResponse:Codable {
let http_status: Int?
let success, has_error: Bool?
let error: [String]?
enum CodingKeys: String, CodingKey {
case http_status = "http_status"
case success = "success"
case has_error = "has_error"
case error = "error"
}
init(http_status: Int?, success: Bool?, has_error: Bool?,error: [String]?) {
self.http_status = http_status
self.success = success
self.has_error = has_error
self.error = error
}
}
现在我已经创建了响应 class,它将暂时处理注册响应:
class RegistrationResponseDetails: Codable {
let token: String?
let verified: Bool?
let message: String?
init(token: String?, verified: Bool?, message: String?) {
self.token = token
self.verified = verified
self.message = message
}
}
假设我需要解析注册响应,这就是我所做的,我创建了一个 class 并同时使用了它们:
class RegistrationResponse: Codable {
let generalResponse:GeneralResponse?
let response: RegistrationResponseDetails?
init(generalResponse: GeneralResponse?, response: RegistrationResponseDetails?) {
self.generalResponse = generalResponse
self.response = response
}
}
所以我会主要使用RegistrationResponse来解析response,response会解析"generalResponse",其中包括http_status、success、has_error、error,然后response会解析想要的响应对象.
但在某些时候 generalResponse 对象总是 nil 并且 response 的数据被正确解析,我应该怎么做才能使 generalResponse 在每个 api 中得到解析而不重复,因为在每个 api 中我将有 generalResponse 对象所以有可能解决它吗?
注意:我正在使用 Alamofire 作为网络库。
对于一个简单的案例
class Main:Decodable {
let name:String? // insert all shared vars
}
class Sub:Main {
let id:String?
}
这将解析
{
"name" : "rr" ,
"id" : "oo"
}
您可以使 GeneralResponse
通用并告诉它在解析响应时使用什么类型:
class GeneralResponse<T: Codable>: Codable {
let http_status: Int?
let success, has_error: Bool?
let error: [String]?
let response: T?
}
class RegistrationResponseDetails: Codable {
let token: String?
let verified: Bool?
let message: String?
}
然后你可以在解析 json:
时给它内部响应 class
let generalResponse = try JSONDecoder().decode(GeneralResponse<RegistrationResponseDetails>.self, from: jsonData)
// generalResponse.response is of type RegistrationResponseDetails?
首先如果
http_status, success, has_error, error are shared between all APIS
为什么 class 属性是可选的?
如果提到的键相同但键 response
的值不同,则使用泛型。
大多数情况下 struct
就足够了。
struct JSONParser<T : Decodable> {
struct Response<U : Decodable> : Decodable {
let httpStatus: Int
let success, hasError: Bool
let error: [String]
let response : U
}
let responseData : Response<T>
init(data: Data) throws {
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
responseData = try decoder.decode(Response.self, from: data)
}
}
然后创建不同的结构,例如
struct RegistrationResponseDetails : Decodable {
let token: String
let verified: Bool
let message: String
}
并解析它
let parser = try JSONParser<RegistrationResponseDetails>(data: data)
let registrationResponseDetails = parser.responseData.response
我有一个 JSON 回复如下:
{
"http_status": 200,
"success": true,
"has_error": false,
"error": [
""
],
"response": {
"token": "",
"verified": false,
"message": ""
}
}
据我所知,对于应用程序 API 用法 http_status、成功、has_error、错误在所有 APIS 之间共享,因此我将创建一个 Codable class 来处理它,但响应可能是不同的模型,所以这就是我正在尝试做的。
我已经创建了一个通用的响应 class 如下,所以这个 class 我可以用于项目中的所有 api 以避免重复相同的 class 但名称不同:
class GeneralResponse:Codable {
let http_status: Int?
let success, has_error: Bool?
let error: [String]?
enum CodingKeys: String, CodingKey {
case http_status = "http_status"
case success = "success"
case has_error = "has_error"
case error = "error"
}
init(http_status: Int?, success: Bool?, has_error: Bool?,error: [String]?) {
self.http_status = http_status
self.success = success
self.has_error = has_error
self.error = error
}
}
现在我已经创建了响应 class,它将暂时处理注册响应:
class RegistrationResponseDetails: Codable {
let token: String?
let verified: Bool?
let message: String?
init(token: String?, verified: Bool?, message: String?) {
self.token = token
self.verified = verified
self.message = message
}
}
假设我需要解析注册响应,这就是我所做的,我创建了一个 class 并同时使用了它们:
class RegistrationResponse: Codable {
let generalResponse:GeneralResponse?
let response: RegistrationResponseDetails?
init(generalResponse: GeneralResponse?, response: RegistrationResponseDetails?) {
self.generalResponse = generalResponse
self.response = response
}
}
所以我会主要使用RegistrationResponse来解析response,response会解析"generalResponse",其中包括http_status、success、has_error、error,然后response会解析想要的响应对象.
但在某些时候 generalResponse 对象总是 nil 并且 response 的数据被正确解析,我应该怎么做才能使 generalResponse 在每个 api 中得到解析而不重复,因为在每个 api 中我将有 generalResponse 对象所以有可能解决它吗?
注意:我正在使用 Alamofire 作为网络库。
对于一个简单的案例
class Main:Decodable {
let name:String? // insert all shared vars
}
class Sub:Main {
let id:String?
}
这将解析
{
"name" : "rr" ,
"id" : "oo"
}
您可以使 GeneralResponse
通用并告诉它在解析响应时使用什么类型:
class GeneralResponse<T: Codable>: Codable {
let http_status: Int?
let success, has_error: Bool?
let error: [String]?
let response: T?
}
class RegistrationResponseDetails: Codable {
let token: String?
let verified: Bool?
let message: String?
}
然后你可以在解析 json:
时给它内部响应 classlet generalResponse = try JSONDecoder().decode(GeneralResponse<RegistrationResponseDetails>.self, from: jsonData)
// generalResponse.response is of type RegistrationResponseDetails?
首先如果
http_status, success, has_error, error are shared between all APIS
为什么 class 属性是可选的?
如果提到的键相同但键 response
的值不同,则使用泛型。
大多数情况下 struct
就足够了。
struct JSONParser<T : Decodable> {
struct Response<U : Decodable> : Decodable {
let httpStatus: Int
let success, hasError: Bool
let error: [String]
let response : U
}
let responseData : Response<T>
init(data: Data) throws {
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
responseData = try decoder.decode(Response.self, from: data)
}
}
然后创建不同的结构,例如
struct RegistrationResponseDetails : Decodable {
let token: String
let verified: Bool
let message: String
}
并解析它
let parser = try JSONParser<RegistrationResponseDetails>(data: data)
let registrationResponseDetails = parser.responseData.response