【发布时间】:2020-11-03 23:48:34
【问题描述】:
我正在使用 Swift 尝试解码 JSON:API 格式的 JSON 结果。我尝试解析的 JSON 具有如下形状:
{
"data": {
"type": "video",
"id": "1",
"attributes": {
"name": "Test Video",
"duration": 1234
}
}
}
我正在尝试创建一个对这些 JSON 对象进行编码的 Swift 结构,但我遇到了 attributes 键的问题,因为它可能包含任意数量的属性。
我试图将上面的 Swift 结构编码成如下所示:
struct JSONAPIMultipleResourceResponse: Decodable {
var data: [JSONAPIResource]
}
struct JSONAPIResource: Decodable {
var type: String
var id: String
var attributes: [String, String]?
}
type 和id 属性应该出现在每个 JSON:API 结果中。 attributes 键应该是任意数量的键值对的列表;键和值都应该是字符串。
然后我尝试从这样的 API 解码 JSON 响应:
let response = try! JSONDecoder().decode(JSONAPIMultipleResourceResponse.self, from: data!)
如果我将type 和id 属性保留在我的JSONAPIResource Swift 结构中,则上述方法有效,但是一旦我尝试对attributes 执行任何操作,我就会收到以下错误:
Fatal error: 'try!' expression unexpectedly raised an error: Swift.DecodingError.valueNotFound(Swift.String, Swift.DecodingError.Context(codingPath: [CodingKeys(stringValue: "data", intValue: nil), _JSONKey(stringValue: "Index 0", intValue: 0), CodingKeys(stringValue: "attributes", intValue: nil), _JSONKey(stringValue: "poster_path", intValue: nil)], debugDescription: "Expected String but found null value instead.", underlyingError: nil)): file /Users/[User]/Developer/[App]/LatestVideosQuery.swift, line 35
2020-07-14 16:13:08.083721+0100 [App][57157:6135473] Fatal error: 'try!' expression unexpectedly raised an error: Swift.DecodingError.valueNotFound(Swift.String, Swift.DecodingError.Context(codingPath: [CodingKeys(stringValue: "data", intValue: nil), _JSONKey(stringValue: "Index 0", intValue: 0), CodingKeys(stringValue: "attributes", intValue: nil), _JSONKey(stringValue: "poster_path", intValue: nil)], debugDescription: "Expected String but found null value instead.", underlyingError: nil)): file /Users/[User]/Developer/[App]/LatestVideosQuery.swift, line 35
我知道 Swift 是非常强类型的,但我不确定如何在 Swift 中编码这些非结构化数据。我的计划是从我的 API 返回资源的通用 JSONAPIResource 表示,然后我可以映射到我的 Swift 应用程序中的模型结构,即将上述 JSON:API 资源转换为 Video 结构。
另外,我试图将attributes 对象中的值天真地转换为字符串,但正如您所见,duration 是一个 整数 值。如果有办法让 attributes 在我的 JSONAPIResource 结构中保留原始值,例如整数和布尔值,而不仅仅是字符串,我会很想知道如何!
【问题讨论】:
-
“任意数量的键值对的列表”。你知道所有可能的值吗?
-
@LeoDabus 不是预先设置,因为属性会根据资源的
type而变化。如果可能的话,我基本上只想要一个键和值的“包”。 -
@MartinBean...您希望最终模型是什么? “一袋键/值”是一个字典,但正如您所见,如果您不能确保值的类型相同,那么您就不能解码它
-
attributes字典不是[String:String],因为duration的值是Int。查看type值和对应的attributes字典之间是否存在一致的依赖关系。如果有一个使用关联类型和一堆不同结构的枚举。 -
@vadian 我知道。我在帖子的末尾注意到了这一点。
标签: json swift codable decodable