ios - 如何在同一容器中解码 DynamicKeys 和 CodingKeys?

标签 ios swift codable decodable

考虑以下 JSON:我正在尝试解码“teams”对象。

let jsonString = """

{
   "Superheroes":{
   "Marvel":"107",
   "DC":"106"
},
"teams":{
  "106":{
     "name":"Marvel",
     "Superheroes":{
        "890":{
           "name":"Batman"
        }
     }
  },
  "107":{
     "name":"DC",
     "Superheroes":{
        "891":{
           "name":"Wonder Woman"
        }
     }
   }
  }
}

"""

我尝试过这样的事情:

struct SuperheroResponse: Decodable {

    let teams: [Team]

    private enum CodingKeys: String, CodingKey {

        case teams = "teams"
    }

    private struct DynamicCodingKeys: CodingKey {
        var stringValue: String
        init?(stringValue: String) {
            self.stringValue = stringValue
        }

        var intValue: Int?
        init?(intValue: Int) {
            return nil
        }
    }

    init(from decoder: Decoder) throws {

        let container = try decoder.container(keyedBy: CodingKeys.self)
        let teamContainer = try container.nestedContainer(keyedBy: CodingKeys.self, forKey: CodingKeys.teams)
        print(teamContainer.allKeys.count)
    
        let tempArray: [Team] = []

        for key in teamContainer.allKeys {

            let decodedObject = try teamContainer.decode(Team.self, forKey: DynamicCodingKeys(stringValue: key.stringValue)!)
            tempArray.append(decodedObject)
        }

        teams = tempArray
   }
}

struct Team: Decodable {

    let name: String
}

我想首先我会获得团队容器,映射按键并从那里继续。问题是 teamContainer.allKeys.count 始终为零。

下面的行也会导致以下错误:无法将“SuperheroResponse.DynamicCodingKeys”类型的值转换为预期的参数类型“SuperheroResponse.CodingKeys”

let decodedObject = try teamContainer.decode(Team.self, forKey: DynamicCodingKeys(stringValue: key.stringValue)!)

最后我将其解码如下:

let jsonData = Data(jsonString.utf8)
let decodedResult = try! JSONDecoder().decode(SuperheroResponse.self, from: jsonData)

dump(decodedResult)

如有任何帮助,我们将不胜感激。理想情况下,我想要类似 SuperheroResponse -> [Team] 的东西, 团队 -> 名称,[ super 英雄], super 英雄 -> 名称

最佳答案

你只是犯了一些小错误。你就快到了。

团队容器由 DynamicCodingKeys 键入:

let teamContainer = try container.nestedContainer(keyedBy: DynamicCodingKeys.self,  // <=
                                                  forKey: .teams)

并且可以使用您提供的 key 对 Teams 进行解码:

let decodedObject = try teamContainer.decode(Team.self, forKey: key)

此外,tempArray 需要是 var:

var tempArray: [Team] = []

或者用map替换该循环:

    teams = try teamContainer.allKeys.map {
        try teamContainer.decode(Team.self, forKey: $0)
    }

一起:

init(from decoder: Decoder) throws {
    let container = try decoder.container(keyedBy: CodingKeys.self)
    let teamContainer = try container.nestedContainer(keyedBy: DynamicCodingKeys.self, forKey: .teams)
    teams = try teamContainer.allKeys.map {
        try teamContainer.decode(Team.self, forKey: $0)
    }
}

关于ios - 如何在同一容器中解码 DynamicKeys 和 CodingKeys?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66807315/

相关文章:

ios - 核心数据导入速度很慢

ios - Swift/交付方法名称到 IBAction 以创建依赖项

ios - 使用 Alamofire 4.0 (Swift 3) 下载文件

ios - 在 iOS 游戏中禁用 iOS 可达性滑动手势

swift - 为什么我可以将 Codable 与 Swift 3.3 的项目语言版本一起使用?

iOS 8 和 AVFoundation : How To Dim Background Audio?

ios - 使用 Swift 设置 Game Center

ios - 调整 NSMutableAttributedString 中字符的垂直高度

swift - 我可以编写类似于 Encodable 和 Decodable 的协议(protocol)吗?

swift - 为什么这样使用 Alamofire 没有发现任何值(value)?