Разобрать Codable классы и избежать повторения - PullRequest
0 голосов
/ 20 декабря 2018

У меня есть ответ JSON:

{
  "http_status": 200,
  "success": true,
  "has_error": false,
  "error": [
    ""
  ],
  "response": {
    "token": "",
    "verified": false,
    "message": ""
  }
}

Насколько я могу сказать, для использования API приложения http_status, success, has_error, error являются общими для всех APIS, и поэтому я создамCodable класс для обработки, но ответ может быть другой моделью, поэтому я пытаюсь сделать вот что.

Я создал общий класс ответа, как показано ниже, поэтому этот класс я могу использовать для всехapis в проекте, чтобы избежать дублирования одного и того же класса, но с разными именами:

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 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 RegistrationResponse: Codable {

    let generalResponse:GeneralResponse?
    let response: RegistrationResponseDetails?

    init(generalResponse: GeneralResponse?, response: RegistrationResponseDetails?) {
        self.generalResponse = generalResponse
        self.response = response
    }
}

Так что я в основном буду использовать RegistrationResponse для анализа ответа, который будет анализировать "generalResponse ", который включает http_status, success, has_error, error, а затем ответ будет анализировать нужный объект ответа.

Но в какой-то момент genОбъект eralResponse всегда равен nil, а в ответе данные анализируются правильно, что мне нужно сделать, чтобы generalResponse анализировался без дублирования в каждом API, потому что в каждом API у меня будет объект GeneralResponse, поэтому возможно ли его решить?

Примечание: Я использую Alamofire в качестве сетевой библиотеки.

Ответы [ 3 ]

0 голосов
/ 20 декабря 2018

Вы можете сделать свой 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:

let generalResponse = try JSONDecoder().decode(GeneralResponse<RegistrationResponseDetails>.self, from: jsonData)
// generalResponse.response is of type RegistrationResponseDetails?
0 голосов
/ 20 декабря 2018

Прежде всего, если

http_status, success, has_error, error являются общими для всех APIS

, почему свойства класса являются необязательными?


Если упомянутые ключи совпадают, но значение для ключа 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
0 голосов
/ 20 декабря 2018

Для простого случая

class Main:Decodable { 
    let name:String?   // insert all shared vars 
} 

class Sub:Main { 
   let id:String? 
} 

Это будет анализировать

{
     "name" : "rr" , 
     "id" : "oo"  
}
...