如何使用Alamofire库解码非JSON格式的API响应
解决非JSON格式API响应的解码问题
你遇到的是Objective-C风格的字典格式响应,不是标准JSON,之前的简单字符替换失效,主要是没处理开头的Data = 前缀,且未避免末尾多余逗号的问题。以下是几种可靠的解码方案:
方案一:精准字符串预处理(修复替换逻辑)
针对给定的响应格式,先清理无效前缀,再针对性替换字符,确保生成合法JSON:
let rawString = " Data = { \"value\" = \"pair\"; \"value2\" = \"pair2\"; }" // 1. 移除开头的"Data = "前缀 var processedString = rawString.replacingOccurrences(of: "Data = ", with: "") // 2. 将键值对的=替换为JSON格式的: processedString = processedString.replacingOccurrences(of: "=", with: ":") // 3. 处理分号:最后一个键值对的分号直接去掉,其余替换为逗号 processedString = processedString.replacingOccurrences(of: "; }", with: "}") processedString = processedString.replacingOccurrences(of: ";", with: ",") // 4. 处理NA为null(按需) processedString = processedString.replacingOccurrences(of: "\"NA\"", with: "null") // 尝试解码 if let data = processedString.data(using: .utf8) { do { let decodedModel = try JSONDecoder().decode(YourCustomModel.self, from: data) // 使用解码后的数据 } catch { print("解码错误:\(error.localizedDescription)") } }
方案二:自定义字符解析器(更稳定)
直接按格式拆分内容,手动提取键值对,适合格式固定的场景,比字符串替换更不容易出错:
// 定义你的数据模型 struct ResponseModel: Codable { let value: String let value2: String } func parseRawResponse(_ rawString: String) -> ResponseModel? { // 提取大括号内的核心内容 guard let startBracket = rawString.firstIndex(of: "{"), let endBracket = rawString.lastIndex(of: "}") else { return nil } let content = rawString[startBracket...endBracket].trimmingCharacters(in: .whitespaces) // 拆分所有键值对 let keyValuePairs = content.components(separatedBy: ";") .map { $0.trimmingCharacters(in: .whitespaces) } .filter { !$0.isEmpty } var modelData = [String: String]() for pair in keyValuePairs { let components = pair.components(separatedBy: "=") .map { $0.trimmingCharacters(in: .whitespacesAndNewlines) } guard components.count == 2 else { continue } // 去除键值两端的引号 let key = components.first?.trimmingCharacters(in: CharacterSet(charactersIn: "\"")) ?? "" let value = components.last?.trimmingCharacters(in: CharacterSet(charactersIn: "\"")) ?? "" // 处理NA为nil(如果模型中对应字段是可选类型) modelData[key] = value == "NA" ? nil : value } // 转模型 if let jsonData = try? JSONSerialization.data(withJSONObject: modelData), let model = try? JSONDecoder().decode(ResponseModel.self, from: jsonData) { return model } // 或者直接初始化模型(更直接) return ResponseModel( value: modelData["value"] ?? "", value2: modelData["value2"] ?? "" ) } // 使用示例 let rawResponse = " Data = { \"value\" = \"pair\"; \"value2\" = \"pair2\"; }" if let model = parseRawResponse(rawResponse) { print(model.value, model.value2) // 输出:pair pair2 }
方案三:正则表达式提取(适配复杂格式)
用正则精准匹配键值对,适合响应格式有轻微变化的场景:
import Foundation func parseWithRegex(_ rawString: String) -> [String: String?] { // 匹配 "key" = "value" 格式的正则 let regexPattern = #"\"(\w+)\" = \"([^\"]*)\""# guard let regex = try? NSRegularExpression(pattern: regexPattern) else { return [:] } let matches = regex.matches(in: rawString, range: NSRange(rawString.startIndex..., in: rawString)) var result = [String: String?]() for match in matches { guard let keyRange = Range(match.range(at: 1), in: rawString), let valueRange = Range(match.range(at: 2), in: rawString) else { continue } let key = String(rawString[keyRange]) let value = String(rawString[valueRange]) result[key] = value == "NA" ? nil : value } return result } // 使用示例 let raw = " Data = { \"value\" = \"pair\"; \"value2\" = \"pair2\"; }" let parsedDict = parseWithRegex(raw) print(parsedDict) // ["value": Optional("pair"), "value2": Optional("pair2")] // 可将字典转成模型使用
为什么之前的替换方法失效?
- 未处理开头的
Data =前缀,导致生成的JSON开头无效; - 直接将所有
;替换为,,会让最后一个键值对后面多出逗号(比如"pair2"; }变成"pair2", }),违反JSON语法规范,最终触发解码失败。
内容的提问来源于stack exchange,提问作者Varun Sharma
相关产品推荐
相关产品推荐

