Swift可编码:无法解码[String:Any]或[String:可解码]类型的字典



在我的自定义初始化器中,我想从JSON解码字典,然后将其值分配给类中的属性。令我惊讶的是,编译器不允许我解码字典,我得到了错误:

Value of protocol type 'Any' cannot conform to 'Decodable'; only struct/enum/class types can conform to protocols

如果我试图解码[String:Decodeable]类型的字典,错误消息会显示:

Value of protocol type 'Decodable' cannot conform to 'Decodable'; only struct/enum/class types can conform to protocols

我的初始值设定项如下:

public let total: Int
required init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
...
if let dict = try container.decodeIfPresent([String: Any].self, forKey: .tracks),
let value = dict["total"] as? Int { // Error is displayed at this line
total = value
} else {
total = 0
}
...
}

当我寻找答案时,我找到了这个答案,根据它,上面的代码应该不会引起任何问题。

您要查找的是nestedContainer。它帮助你"跳过";JSON中的层次结构级别。Ie:让我们想象一下,在你的代码中,它都在同一级别(一个结构(,但在JSON中,它不是,有一个子字典。

出于测试目的,您的JSON可能看起来像:

{
"title": "normal",
"tracks": {
"name": "myName",
"total": 3
}
}

如果我们想在我们的模型中:

struct TestStruct: Codable {
let title: String
let name: String
let total: Int
}

我们需要使用nestedContainer(keyedBy: forKey:):

extension TestStruct {
enum TopLevelKeys: String, CodingKey {
case title
case tracks
}

enum NestedLevelCodingKeys: String, CodingKey {
case name
case total
}

init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: TopLevelKeys.self)
self.title = try container.decode(String.self, forKey: .title)
let subcontainer = try container.nestedContainer(keyedBy: NestedLevelCodingKeys.self, forKey: TopLevelKeys.tracks)
self.name = try subcontainer.decode(String.self, forKey: .name)
self.total = try subcontainer.decode(Int.self, forKey: .total) //You can use here a `decodeIfPresent()` if needed, use default values, etc.
}
}

在您的示例中,您将decodeIfPresent()用于子分区。目前尚不清楚这是出于测试目的,还是有时子词典不存在。如果是这样的话,你可以有一个像这样的JSON:

{
"title": "normal"
} 

然后,在调用nestedContainer(keyedBy: forKey:)之前,如果else的情况需要,请使用if container.contains(TopLevelKeys.tracks) {}并设置默认值。

相关内容

  • 没有找到相关文章

最新更新