Я получаю данные с моего Gitlab-сервера с помощью Alamofire и, похоже, не могу правильно установить CodingKey.
Вот две модели, которые я использую для этого (сокращенно):
struct Issue: Codable {
let id: Int
var iid: Int? = nil
var project_id: Int? = nil
var state: String?
var title: String? = nil
var description: String? = nil
var labels: [Label]? = [] // custom type, see below
}
struct Label {
let id: Int
var name: String
var color: String = "#FFAABB"
var labelDescription: String = ""
}
extension Label: CustomStringConvertible {
var description: String {
return "Label: \(name)"
}
}
extension Label: Codable {
enum CodingKeys: String, CodingKey {
case id
case name
case color
case labelDescription = "description"
}
}
extension Label: Equatable {
static func ==(lhs: Label, rhs: Label) -> Bool {
return lhs.id == rhs.id
}
}
Теперь, при получении моих проблем с Alamofire, я вижу, что JSON возвращается, например,
{
"id": 402,
"iid": 78,
"project_id": 34,
"title": "Feature: Prioritization / Order of issues in table view",
"description": "On the web, it is possible to have the issues ordered differently (e.g. by date added or manually).\n\nCheck, how `manually` is implemented and whether this ordering information is coming with the api.\nIf it is, could this be used to do reorders in the tableview?",
"state": "opened",
"created_at": "2020-03-26T14:08:21.355Z",
"updated_at": "2020-03-27T12:58:03.418Z",
"closed_at": null,
"closed_by": null,
"labels": [{
"id": 81,
"name": "P1",
"color": "#428BCA",
"description": "Priority 1 of 4",
"description_html": "Priority 1 of 4",
"text_color": "#FFFFFF"
}],
...
}
Кодирование завершается неудачно, хотя Alamofire показывает следующую ошибку:
[Request]: GET https: //dev.appfros.ch/api/v4/projects/34/labels
[Request Body]:
None
[Response]:
[Status Code]: 200
[Headers]:
Cache-Control: max-age=0, private, must-revalidate
Content-Length: 929
Content-Type: application/json
Date: Fri, 27 Mar 2020 14:08:59 GMT
Etag: W/\"758e92848542f37113453292b85cbe17\"
Link: <https://dev.appfros.ch/api/v4/projects/34/labels?id=34&include_ancestor_groups=true&page=1&per_page=20&with_counts=false>; rel=\"first\", <https://dev.appfros.ch/api/v4/projects/34/labels?id=34&include_ancestor_groups=true&page=1&per_page=20&with_counts=false>; rel=\"last\"
Server: nginx/1.17.6
Strict-Transport-Security: max-age=31536000, max-age=31536000
Vary: Origin
referrer-policy: strict-origin-when-cross-origin
x-content-type-options: nosniff
x-frame-options: SAMEORIGIN
x-next-page:
x-page: 1
x-per-page: 20
x-prev-page:
x-request-id: BdvjZaS8hl4
x-runtime: 0.052360
x-total: 5
x-total-pages: 1
[Response Body]:
[{\"id\":81,\"name\":\"P1\",\"color\":\"#428BCA\",\"description\":\"Priority 1 of 4\",\"description_html\":\"Priority 1 of 4\",\"text_color\":\"#FFFFFF\",\"subscribed\":false,\"priority\":null,\"is_project_label\":true},{\"id\":82,\"name\":\"P2\",\"color\":\"#428BCA\",\"description\":\"Priority 2 of 4\",\"description_html\":\"Priority 2 of 4\",\"text_color\":\"#FFFFFF\",\"subscribed\":false,\"priority\":null,\"is_project_label\":true},{\"id\":83,\"name\":\"P3\",\"color\":\"#428BCA\",\"description\":\"Priority 3 of 4\",\"description_html\":\"Priority 3 of 4\",\"text_color\":\"#FFFFFF\",\"subscribed\":false,\"priority\":null,\"is_project_label\":true},{\"id\":84,\"name\":\"P4\",\"color\":\"#428BCA\",\"description\":\"Priority 4 of 4\",\"description_html\":\"Priority 4 of 4\",\"text_color\":\"#FFFFFF\",\"subscribed\":false,\"priority\":null,\"is_project_label\":true},{\"id\":79,\"name\":\"WIP\",\"color\":\"#004E00\",\"description\":null,\"description_html\":\"\",\"text_color\":\"#FFFFFF\",\"subscribed\":false,\"priority\":null,\"is_project_label\":true}]
[Data]: 929 bytes
[Network Duration]: 0.3039969205856323s
[Serialization Duration]: 0.003159046173095703s
[Result]: failure(Alamofire.AFError.responseSerializationFailed(reason: Alamofire.AFError.ResponseSerializationFailureReason.decodingFailed(error: Swift.DecodingError.valueNotFound(Swift.String, Swift.DecodingError.Context(codingPath: [_JSONKey(stringValue: \"Index 4\", intValue: 4), CodingKeys(stringValue: \"description\", intValue: nil)], debugDescription: \"Expected String value but found null instead.\", underlyingError: nil)))))
Кроме того, тестирование показывает, что когда я опускаю клавишу description
типа Label
, все работает. Очевидно, я хочу преобразовать ключ description
в labelDescription
в моей модели, потому что description
уже необходим для соответствия CustomStringConvertible
- но даже когда я удаляю это соответствие и изменяю свою модель Labels
на следующую, Я получаю ошибку ...
struct Label {
let id: Int
var name: String
var color: String = "#FFAABB"
var description: String = ""
}