SwiftyJSON模型构建及嵌套数组字典的API调用问题排查
解决SwiftyJSON解析数组套字典API时单个Note实例获取所有noteimages的问题
你遇到的问题很典型——在解析嵌套数组的API响应时,单个Note实例意外获取了所有noteimages数据,而不是只属于自己的图片。先梳理下你的场景:
场景回顾
- 目标:用SwiftyJSON解析包含数组套字典结构的API响应,每个
Note对应自己专属的noteimages数组 - 示例API数据结构:
Data: [ { "id": 1, "title": "some title", "details": "here are some details", "userId": 1, "hidden": false, "createdAt": "2018-02-14T07:02:33.000Z", "updatedAt": "2018-02-14T07:02:33.000Z", "contactId": 1, "noteimages": [ { "id": 2, "imageUrl": "someimage222.jpg", "userId": 1, "hidden": false, "createdAt": "2018-02-14T07:02:58.000Z", "updatedAt": "2018-02-15T04:41:05.000Z", "noteId": 1 }, { "id": 2, "imageUrl": "someimage222.jpg", "userId": 1, "hidden": false, "createdAt": "2018-02-14T07:02:58.000Z", "updatedAt": "2018-02-15T04:41:05.000Z", "noteId": 1 } ] } ]
- 你的异常代码:
var notes = [Note]() // 原代码漏了数组括号,这里修正 var noteImages = [NoteImage]() // 同样修正为数组类型 .... Alamofire.request(url, method: .get, parameters: nil, encoding: JSONEncoding.default, headers: header).responseJSON { (response) in if response.result.error == nil { guard let data = response.data else { return } do { if let json = try JSON(data: data).array { print(json) for item in json { let title = item["title"].stringValue let details = item["details"].stringValue //loop through nested array for innerItem in item["noteimages"].arrayValue { let noteImage = NoteImage(imageUrl: innerItem["imageUrl"].stringValue) self.noteImages.append(noteImage) } print("note images: \(self.noteImages)") let note = Note(title: title, details: details, noteImage: self.noteImages) self.notes.append(note) } completion(true) } } catch { debugPrint(error) } } else { completion(false) debugPrint(response.result.error as Any) } }
问题根源
你定义的noteImages是一个全局/外部共享数组,每次循环处理新的Note时,只是把当前Note的图片追加到这个数组里,没有清空或重新初始化。这就导致:
- 第一个Note处理时,
noteImages里是它自己的图片 - 第二个Note处理时,会把自己的图片追加到已有数组,所以第二个Note的
noteImage属性就包含了第一个+第二个的图片 - 以此类推,后面的Note会累积所有之前的图片
解决方案
我们需要让每个Note拥有自己独立的图片数组,而不是共享一个全局数组。具体步骤:
1. 调整模型结构(确保Note持有专属图片数组)
// 假设你的NoteImage模型定义 struct NoteImage { let imageUrl: String } // 修正Note模型,让它包含自己的noteImages数组 struct Note { let title: String let details: String let noteImages: [NoteImage] // 命名更规范,明确是数组类型 }
2. 修改API解析逻辑(为每个Note创建局部图片数组)
// 移除全局的noteImages数组! var notes = [Note]() Alamofire.request(url, method: .get, parameters: nil, encoding: JSONEncoding.default, headers: header).responseJSON { (response) in if response.result.error == nil { guard let data = response.data else { completion(false) return } do { let jsonArray = try JSON(data: data).array guard let notesJson = jsonArray else { completion(false) return } for noteJson in notesJson { let title = noteJson["title"].stringValue let details = noteJson["details"].stringValue // 👉 关键:为当前Note创建局部的图片数组,仅存储当前Note的图片 var currentNoteImages = [NoteImage]() for imageJson in noteJson["noteimages"].arrayValue { let imageUrl = imageJson["imageUrl"].stringValue let noteImage = NoteImage(imageUrl: imageUrl) currentNoteImages.append(noteImage) } // 用局部数组创建专属Note实例 let note = Note(title: title, details: details, noteImages: currentNoteImages) self.notes.append(note) print("当前Note的图片数量:\(currentNoteImages.count)") } completion(true) print("所有Note解析完成:\(self.notes.count)个") } catch { debugPrint(error) completion(false) } } else { completion(false) debugPrint(response.result.error as Any) } }
额外优化建议
可以给模型添加JSON初始化扩展,让解析逻辑更简洁易维护:
extension NoteImage { init?(json: JSON) { guard let imageUrl = json["imageUrl"].string else { return nil } self.imageUrl = imageUrl } } extension Note { init?(json: JSON) { guard let title = json["title"].string, let details = json["details"].string else { return nil } self.title = title self.details = details // 用compactMap自动过滤无效的图片数据 self.noteImages = json["noteimages"].arrayValue.compactMap(NoteImage.init) } } // 简化后的解析逻辑 for noteJson in notesJson { if let note = Note(json: noteJson) { self.notes.append(note) } }
内容的提问来源于stack exchange,提问作者imgroot
相关产品推荐
相关产品推荐

