我正在使用Alamofire从Gitlab服务器获取数据,似乎无法正确设置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).nnCheck, 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)))))
此外,测试表明,当我省略类型为Label
的description
键时,一切都正常。显然,我想在我的模型中将description
密钥转换为labelDescription
,因为description
已经需要符合CustomStringConvertible
——但即使我删除了这种一致性并将Labels
模型更改为以下模型,我也会收到错误。。。
struct Label {
let id: Int
var name: String
var color: String = "#FFAABB"
var description: String = ""
}
您可以覆盖init(from decoder:)
和decodeIfPresent(_,forKey:)
从文件来看:
如果容器没有值,则此方法返回
nil
或者如果值是null
。两者之间的差异这些状态可以通过CCD_ 12调用来区分。
在您的情况下:
extension Label {
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
id = try container.decode(Int.self, forKey: .id)
name = try container.decode(String.self, forKey: .name)
color = try container.decode(String.self, forKey: .color)
labelDescription = try container.decodeIfPresent(String.self, forKey: .labelDescription) ?? ""
}
}