Swift 5中如何安全地将带分隔符的数组解析为键值对
安全解析键值对数组为字典/模型(Swift 5)
我明白你想把这种键值对格式的数组安全转换成可用的字典或者模型,之前尝试用Decodable没成功对吧?其实不用纠结Decodable直接转,先把数组处理成字典会更直接,之后如果需要转模型也很方便。下面分两种场景给你具体实现:
场景1:原始字符串数组(如 ["BirthDate=1976-09-11", "Name=Smith", "Status=Alive"])
我们可以写一个安全的转换函数,自动过滤掉格式不正确的元素(比如没有=或者拆分后不是两个部分的字符串),避免崩溃:
func parseKeyValueArray(_ array: [String]) -> [String: String] { var result = [String: String]() for item in array { // 只拆分第一个=,避免value里包含=符号的情况(比如"Bio=I'm=Smith") let components = item.split(separator: "=", maxSplits: 1) guard components.count == 2 else { // 格式不对,跳过这个元素 continue } let key = String(components[0]).trimmingCharacters(in: .whitespaces) let value = String(components[1]).trimmingCharacters(in: .whitespaces) result[key] = value } return result } // 使用示例 let inputArray = ["BirthDate=1976-09-11", "Name=Smith", "Status=Alive", "InvalidItem"] let dictionary = parseKeyValueArray(inputArray) print(dictionary) // 输出:["BirthDate": "1976-09-11", "Name": "Smith", "Status": "Alive"]
场景2:已经拆分后的二维Substring数组(如 [["BirthDate", "1976-09-11"], ...])
这种情况更简单,只要检查每个子数组的长度是2,再转成String类型的字典即可:
func parseSplitKeyValueArray(_ array: [[Substring]]) -> [String: String] { var result = [String: String]() for pair in array { guard pair.count == 2 else { continue } let key = String(pair[0]).trimmingCharacters(in: .whitespaces) let value = String(pair[1]).trimmingCharacters(in: .whitespaces) result[key] = value } return result } // 使用示例 let splitArray = ["BirthDate=1976-09-11", "Name=Smith"].map { $0.split(separator: "=") } let splitDictionary = parseSplitKeyValueArray(splitArray) print(splitDictionary)
关于Decodable的使用
你之前尝试用Decodable转字典没成功,是因为Decodable默认是针对JSON结构的,而这种键值对数组并不是标准的JSON对象格式。不过如果最终要转成自定义模型,我们可以先把数组转成字典,再通过字典来解码模型:
比如先定义一个模型:
struct Person: Decodable { let birthDate: String let name: String let status: String // 自定义编码键,匹配字典里的key enum CodingKeys: String, CodingKey { case birthDate = "BirthDate" case name = "Name" case status = "Status" } }
然后把之前得到的字典转成Data,再解码:
// 先拿到字典 let dictionary = parseKeyValueArray(inputArray) // 转成Data guard let jsonData = try? JSONSerialization.data(withJSONObject: dictionary) else { fatalError("Failed to convert dictionary to data") } // 解码成模型 do { let person = try JSONDecoder().decode(Person.self, from: jsonData) print(person.name) // 输出 Smith } catch { print("Decoding error: \(error)") }
或者更直接的,不用Decodable,直接用字典初始化模型(这种方式更简单,适合这种简单的键值对场景):
extension Person { init?(dictionary: [String: String]) { guard let birthDate = dictionary["BirthDate"], let name = dictionary["Name"], let status = dictionary["Status"] else { return nil } self.birthDate = birthDate self.name = name self.status = status } } // 使用 if let person = Person(dictionary: dictionary) { print(person.birthDate) // 输出 1976-09-11 }
这样处理既安全又灵活,能应对各种格式不规范的情况,避免崩溃。
内容的提问来源于stack exchange,提问作者raurora
相关产品推荐
相关产品推荐

