将 API JSON 数据转换为 Swift 结构

Converting API JSON data to a Swift struct

我是第一次使用 Swift,我希望能够将来自 API 响应的一些信息处理成可用的 Swift 对象。

我有(例如)从我的 API 返回的以下数据:

{
    data: [{
       id: 1,
       name: "Fred",
       info: {
           faveColor: "red",
           faveShow: "Game of Thrones",
           faveIceCream: "Chocolate",
           faveSport: "Hockey",
       },
       age: "28",
       location: "The Moon",
    },{
        ...
    }]
}

在 swift 我有 data 从 API 返回。我得到了 第一个对象,我正在转换它并像这样访问它:

let json = try! JSONSerialization.jsonObject(with: data, options: []) as! [String: Any]
let dataParentNode = json["data"] as! [[String:Any]]
let firstObject = dataParentNode[0]

let _id = firstObject["id"] as? String ?? "0"
let _name = firstObject["name"] as? String ?? "Unknown"

这很好,直到我想开始处理属于第一个对象的子对象,所以我想出了以下 structs 来尝试使它更干净。

请注意 - 我不需要处理返回的所有 JSON 数据,因此我想将其转换为我在结构中需要的数据

struct PersonInfo : Codable {
    let faveColor: String?
    let faveShow: String?
}

struct Person : Codable {
   let id: String?
   let name: String?
   let info: PersonInfo?
}

我拿这个的时候:

let json = try! JSONSerialization.jsonObject(with: data, options: []) as! [String: Any]
let dataParentNode = json["data"] as! [[String:Any]]
let firstObject = dataParentNode[0]

然后尝试将 firstObject 转换为 Person 或将 firstObject["info"] 转换为 PersonInfo 我似乎无法让它工作(我得到 nil).

let personInfo = firstObject["info"] as? PersonInfo

有人可以指点一下吗?我只需要集中精力获取 API 响应数据并将其映射到给定的结构(带有子对象),而忽略我不需要的键。

您可以简单地使用 JSONDecoderdecode(_:from:) 函数来实现:

let decoder = JSONDecoder()
do {
    let decoded = try decoder.decode([String: [Person]].self, from: data)
    let firstObject = decoded["data"]?.first
} catch {
    print(error)
}

更好的是,您可以像这样向您的模型添加另一个结构:

struct PersonsData: Codable {
    let data: [Person]
}

并使用该类型映射您的 JSON:

let decoder = JSONDecoder()
do {
    let decoded = try decoder.decode(PersonsData.self, from: data)
    let firstObject = decoded.data.first
} catch {
    print(error)
}

更新:您的 Person 结构可能需要稍作更改,因为 id 属性 在您的 JSON.

中是整​​数

所以,结果会是这样:

struct Person : Codable {
   let id: Int?
   let name: String?
   let info: PersonInfo?
}