带有密钥描述的JSON



我正在使用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)))))

此外,测试表明,当我省略类型为Labeldescription键时,一切都正常。显然,我想在我的模型中将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) ?? ""
}
}

相关内容

  • 没有找到相关文章

最新更新