【问题标题】:Manually Parsing a a JSON into an Object of a Struct手动将 JSON 解析为 Struct 的对象
【发布时间】:2020-05-28 18:04:37
【问题描述】:

我是 swift 的初学者,我目前正在制作一个发出网络请求的应用程序。我一直在尝试解析这个 JSON 数据,但是嵌套数据真的很难让我理解:

 "abilities": [
            {
                "ability": {
                    "name": "chlorophyll",
                    "url": "https://pokeapi.co/api/v2/ability/34/"
                },
                "is_hidden": true,
                "slot": 3
            },
            {
                "ability": {
                    "name": "overgrow",
                    "url": "https://pokeapi.co/api/v2/ability/65/"
                },
                "is_hidden": false,
                "slot": 1
            }
        ]

JSON 序列化代码

let jsonAny = try JSONSerialization.jsonObject(with: data, options: [])
            guard let json = jsonAny as? [String: Any] else { return }

这是我手动解析 JSON 数据的尝试

    private func parsePokemonManual(json: [String: Any]) -> Pokemon {
        let abilities = json["abilities"] as? [String: Any] ?? [String: Any]()

        return Pokemon(abilities: abilities)
    }
}

这些是我用来保存数据的结构。

struct Abilities {
    let ability : Ability

    struct Ability {
        let name : String
    }
}

如何成功地将 JSON 数据解析为 Pokemon 结构的对象?

这段代码太胖了,我收到错误“无法将类型'[String:Any]'的值转换为预期的参数类型'[Abilities]'。我的问题是我不知道要转换什么类型我的结构“能力”也不正确。

【问题讨论】:

  • 嗨凯尔,欢迎来到 SO!感谢您的问题的详细程度。您能否添加一些细节来描述实际出了什么问题?当您尝试解析 JSON 或尝试访问已解析对象内的对象时,代码是否失败?您可以发布错误消息吗?这些可能会帮助您得到答案!

标签: swift


【解决方案1】:

您的尝试存在 3 个问题,尽管有人可能会争辩说只有 1 个,您应该使用 Codable 代替,但让我们在这里使用 JSONSerialization。问题是

  • 您读取的 json 有误,在访问“功能”时不应转换为字典,而是转换为字典数组
  • 你的结构很复杂,可能是因为之前的问题
  • 最后,您不能转换为自定义类型,您需要通过准确说明要使用哪些值以及如何使用来将数据转换或映射到您的类型,因为编译器不了解如何使用去做。

首先结构可以简化为

struct Ability {
    let name : String
}

其余的固定在函数parsePokemonManual中。首先获取“能力”并转换为一系列字典。然后通过获取“能力”来映射数组中的每个项目并将其转换为用于获取“名称”值的字典,然后在创建Ability 的实例时使用该值

private func parsePokemonManual(json: [String: Any]) -> [Ability] {
    guard let abilities = json["abilities"] as? [[String: Any]] else {
        return []
    }

    return abilities.compactMap { dict in
        guard let ability = dict["ability"] as? [String: String], let name = ability["name"] else { return nil }

        return Ability(name: name)
    }
}

【讨论】:

    猜你喜欢
    • 2012-05-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-27
    • 2014-10-17
    相关资源
    最近更新 更多