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
相关产品推荐
相关产品推荐

