You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 07:52:58