【问题标题】:Expected to decode Dictionary<String, Any> but found an array instead JSON SwiftUI预期解码 Dictionary<String, Any> 但找到一个数组而不是 JSON SwiftUI
【发布时间】:2020-06-02 19:42:14
【问题描述】:

我在尝试使用 SwiftUI 解码 JSON 时遇到错误。

typeMismatch(Swift.Dictionary, Swift.DecodingError.Context(codingPath: [_JSONKey(stringValue: "Index 0", intValue: 0), CodingKeys(stringValue: "platforms", intValue: nil)], debugDescription: "本应解码字典,但找到了一个数组。",underlyingError: nil))

我相信这与找到一个带有平台的空数组有关,但我试图弄清楚如何调用该信息,然后在内容视图中显示它。

我认为这是因为我在 getGames 网络服务中使用了字段,我可能搞砸了我拉取 API 的方式。我也不知道在哪里打印 JSON,所以我可以看到实际被拉取的内容。

我要解码的 JSON 是:

{
    "id": 22636,
    "name": "Call of Duty: Black Ops - Annihilation",
    "platforms": [
      {
        "id": 6,
        "name": "PC (Microsoft Windows)"
      },
      {
        "id": 9,
        "name": "PlayStation 3"
      },
      {
        "id": 12,
        "name": "Xbox 360"
      }
    ]
}

我的游戏结构看起来像:

Game.swift
struct Game: Codable, Identifiable {
    let id: Int
    let name: String
    let summary: String?
    let platforms: Platforms
}

struct Platforms: Codable, Identifiable {
    let id: Int
    let name: String

}

我的 Web 服务使用字段来仅获取 API 的特定部分:

GameService.swift
public class GameService: ObservableObject {

    @Published var games = [Game]()

    init(){
        getGames()
    }

    func getGames() {

        let parameters = "fields name, summary, platforms.name; where platforms = (48,6,49); limit 10;"
        let postData = parameters.data(using: .utf8)

        let url = URL(string: "https://api-v3.igdb.com/games/")!

        var request = URLRequest(url: url)
        request.addValue("HIDDEN", forHTTPHeaderField: "user-key")
        request.httpMethod = "POST"
        request.addValue("application/json", forHTTPHeaderField: "Content-Type")
        request.httpBody = postData

        URLSession.shared.dataTask(with: request) { data, response, error in
            do {
                if let d = data {
// DO I NEED TO ADJUST THE JSONDecoder to Array<Game>.self?
                    let decodedLists = try JSONDecoder().decode([Game].self, from: d)
                    DispatchQueue.main.async {
                        self.games = decodedLists
                    }
                } else {
                    print("No data in response: \(error?.localizedDescription ?? "Unknown Error").")
                }
            } catch {
                print("\(error)")
            }
        }.resume()
    }
}

【问题讨论】:

  • 平台是一个数组。就这样更新吧:let platforms: [Platforms]
  • @FrancescoDeliro 当我尝试得到一个 Xcode 错误时说类型 [Platforms] 没有成员“名称”
  • 是的,因为现在您必须处理一个数组而不是单个值。你在哪里得到错误?
  • @FrancescoDeliro 在视图中。文本(game.platforms.name)
  • 我回答添加了一个例子。让我知道它是否适合你

标签: ios json swift swiftui


【解决方案1】:

您在 JSON 中接收到一个平台数组,因此您必须更新您的 Game 结构才能解析它:

struct Game: Codable, Identifiable {
    let id: Int
    let name: String
    let summary: String?
    let platforms: [Platforms]
}

并使用它,例如:

List {
    ForEach(game.platforms) { platform in
        Text(platform.name)
    }
}

【讨论】:

  • 仍然获得类型 [platforms] 的值没有成员“名称”。 ``` VStack { List(gamesList.games) { VStack 中的游戏(对齐方式:.leading){ Text(game.name) if game.summary != nil { Text(game.summary ?? "No Game Summary")} ForEach(game.platforms) { platform in Text(platform.name) } } } } ``` 我观察到的对象是调用 GameService() 的 gamesList
  • 您是否更新了所有使用 game.platforms.name 的地方?
  • 我想通了。我的 Platforms Struct 外壳不在我的 Game 结构内。随时更新您的答案,我会将其标记为正确。谢谢你!
  • 欢迎您@andywalt!好的!答案与您关于解析错误的问题有关:) 但您可以编辑您的问题,显示修复错误后如何处理数组!谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-09-23
相关资源
最近更新 更多