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

iOS开发:如何通过JSON将发票客户ID转换为客户名称?

解决发票客户ID转客户名称的方案

看起来你已经有了获取客户数据的基础函数,接下来咱们一步步实现把发票里的客户ID转换成对应名称的逻辑,核心思路是先缓存客户数据到一个字典里,这样后续查找效率会很高。

第一步:定义数据模型(Codable)

首先得把接口返回的JSON转换成Swift的模型,这样解析起来更直观。你可以根据实际接口返回的字段调整以下模型:

// 客户模型,对应接口返回的字段
struct Client: Codable {
    let id: String // 如果接口返回的是数字ID,就改成Int类型
    let name: String
    // 其他你需要的字段,比如联系方式、地址等,按需添加
}

// 发票模型,包含关联的客户ID字段
struct Invoice: Codable {
    let id: String
    let customerId: String // 注意这里的类型要和Client的id完全一致
    // 其他发票相关字段,比如金额、开票日期等
}

第二步:缓存客户ID-名称映射

在你的ClientsViewController里,添加一个类级别的字典来存储客户ID和名称的对应关系,这样后续不用每次都去请求接口:

class ClientsViewController: UIViewController {
    // 客户ID到名称的映射字典,初始为空
    private var clientsIdToName: [String: String] = [:]
    
    // 完善你已有的downloadClientsJSON函数,添加解析和缓存逻辑
    func downloadClientsJSON(completed: @escaping () -> ()) {
        guard let url = URL(string: "http://ex.com/app/api/clientList/get") else {
            print("无效的客户接口URL")
            completed()
            return
        }
        
        URLSession.shared.dataTask(with: url) { [weak self] data, response, error in
            guard let self = self else { return }
            
            if let error = error {
                print("下载客户数据出错: \(error.localizedDescription)")
                completed()
                return
            }
            
            guard let data = data else {
                print("没有获取到客户数据")
                completed()
                return
            }
            
            do {
                // 解析接口返回的客户数组
                let clients = try JSONDecoder().decode([Client].self, from: data)
                // 转换为ID-名称的字典,方便快速查找
                self.clientsIdToName = Dictionary(uniqueKeysWithValues: clients.map { ($0.id, $0.name) })
                completed()
            } catch {
                print("解析客户数据失败: \(error)")
                completed()
            }
        }.resume()
    }
}

第三步:处理发票数据,转换客户ID为名称

这里要注意异步顺序问题:必须确保客户数据已经下载完成,再去处理发票里的客户ID转换。你可以这样写下载发票的逻辑:

extension ClientsViewController {
    func downloadInvoicesJSON() {
        guard let url = URL(string: "http://ex.com/app/api/invoiceList/get") else {
            print("无效的发票接口URL")
            return
        }
        
        URLSession.shared.dataTask(with: url) { [weak self] data, response, error in
            guard let self = self else { return }
            
            if let error = error {
                print("下载发票数据出错: \(error.localizedDescription)")
                return
            }
            
            guard let data = data else {
                print("没有获取到发票数据")
                return
            }
            
            do {
                let invoices = try JSONDecoder().decode([Invoice].self, from: data)
                
                // 检查客户字典是否为空,如果为空先下载客户数据
                if self.clientsIdToName.isEmpty {
                    self.downloadClientsJSON {
                        // 客户数据下载完成后,再处理发票
                        self.processInvoices(invoices)
                    }
                } else {
                    // 客户数据已缓存,直接处理发票
                    self.processInvoices(invoices)
                }
            } catch {
                print("解析发票数据失败: \(error)")
            }
        }.resume()
    }
    
    // 处理发票数据,完成ID到名称的转换
    private func processInvoices(_ invoices: [Invoice]) {
        DispatchQueue.main.async {
            // 这里可以更新你的UI,比如表格视图、标签等
            for invoice in invoices {
                // 通过客户ID获取名称,找不到时显示默认值避免空值
                let customerName = self.clientsIdToName[invoice.customerId] ?? "未知客户"
                print("发票\(invoice.id) 对应的客户: \(customerName)")
                // 把customerName赋值给你的UI元素即可
            }
        }
    }
}

关键注意事项

  • 类型一致性:确保Client.id和Invoice.customerId的类型完全匹配(都是String或者都是Int),否则字典查找会失败。
  • UI线程安全:更新UI的操作必须放到主队列(DispatchQueue.main.async)里,避免线程崩溃。
  • 容错处理:当找不到对应客户ID的名称时,设置一个默认值(比如“未知客户”),避免出现空值问题。

内容的提问来源于stack exchange,提问作者andreaem

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 07:48:53