iOS Swift如何从SOAP API响应的XML中提取JSON及可用库咨询
解决SOAP响应中XML嵌套JSON的Swift解析问题
刚接触SOAP确实容易踩这种混合格式的坑,我之前对接老系统的时候也碰到过一模一样的问题,给你整理几个在Swift里可行的方案,亲测好用:
一、用Swift标准库搞定,零额外依赖
Swift自带的XMLParser就能帮你先把XML里嵌套的JSON字符串抽出来,之后再用JSONDecoder解析成你需要的模型,完全不需要第三方库。
举个例子,假设你的SOAP响应XML结构大概是这样:
<soap:Envelope> <soap:Body> <GetDataResponse> <Result>{"userId": 123, "userName": "John", "orders": [{"id": 1, "price": 99.9}]}</Result> </GetDataResponse> </soap:Body> </soap:Envelope>
你可以写个简单的XML解析代理类来提取<Result>标签里的JSON内容:
class XMLJSONExtractor: NSObject, XMLParserDelegate { private var currentElement = "" private var jsonContent = "" private var isExtractingTarget = false func extractJSON(from xmlData: Data) -> String? { let parser = XMLParser(data: xmlData) parser.delegate = self parser.parse() return jsonContent.trimmingCharacters(in: .whitespacesAndNewlines) } // 开始解析某个标签时触发 func parser(_ parser: XMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, attributes attributeDict: [String : String] = [:]) { currentElement = elementName // 这里替换成你实际存放JSON的标签名,比如我这里是"Result" if elementName == "Result" { isExtractingTarget = true } } // 读取标签内的文本内容 func parser(_ parser: XMLParser, foundCharacters string: String) { if isExtractingTarget { jsonContent += string } } // 结束解析某个标签时触发 func parser(_ parser: XMLParser, didEndElement elementName: String, namespaceURI: String?, qualifiedName qName: String?) { if elementName == "Result" { isExtractingTarget = false } } }
使用的时候就这么写:
// 假设你从API请求拿到的响应数据是xmlData let extractor = XMLJSONExtractor() guard let jsonString = extractor.extractJSON(from: xmlData) else { print("Failed to get JSON from XML") return } // 把JSON字符串转成Data,再用Codable解析成模型 if let jsonData = jsonString.data(using: .utf8) { do { let userModel = try JSONDecoder().decode(User.self, from: jsonData) // 这里就拿到解析好的模型了,直接用就行 print("User name: \(userModel.userName)") } catch { print("JSON decode error: \(error.localizedDescription)") } }
二、Alamofire完全适用,搭配XML库更省心
Alamofire是iOS开发中常用的网络库,完全能处理这种场景。你可以配合纯Swift的XML解析库AEXML来简化XML解析步骤,代码会更简洁。
首先把AEXML加到你的项目里(用Swift Package Manager或者CocoaPods都可以),然后写请求代码:
import Alamofire import AEXML // 先自定义SOAP的请求编码,因为Alamofire默认编码不适合SOAP struct SOAPRequestEncoding: ParameterEncoding { func encode(_ urlRequest: URLRequestConvertible, with parameters: Parameters?) throws -> URLRequest { var request = try urlRequest.asURLRequest() // 设置SOAP请求的Content-Type request.setValue("text/xml; charset=utf-8", forHTTPHeaderField: "Content-Type") // 这里替换成你在Postman里用的SOAP信封内容,把参数填进去 let soapEnvelope = """ <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> <soap:Body> <GetDataRequest> <UserId>123</UserId> </GetDataRequest> </soap:Body> </soap:Envelope> """ request.httpBody = soapEnvelope.data(using: .utf8) return request } } // 发起SOAP请求 AF.request("你的SOAP接口URL", method: .post, encoding: SOAPRequestEncoding()) .responseData { response in switch response.result { case .success(let data): do { // 解析XML文档 let xmlDoc = try AEXMLDocument(xml: data) // 按照XML路径找到存放JSON的节点,替换成你实际的路径 let jsonString = xmlDoc.root["soap:Body"]["GetDataResponse"]["Result"].value ?? "" guard let jsonData = jsonString.data(using: .utf8) else { print("Invalid JSON string") return } // 解析成模型 let userModel = try JSONDecoder().decode(User.self, from: jsonData) // 处理模型数据 } catch { print("Parsing error: \(error.localizedDescription)") } case .failure(let error): print("Request failed: \(error.localizedDescription)") } }
三、如果想用SwiftyJSON,这么做就行
如果你习惯用SwiftyJSON处理JSON,那提取出JSON字符串之后,直接转成SwiftyJSON对象就可以了:
if let jsonData = jsonString.data(using: .utf8) { let json = JSON(jsonData) // 然后用SwiftyJSON的语法取值,比如 let userName = json["userName"].stringValue let orderCount = json["orders"].count }
最后划个重点
不管用哪种方案,核心思路都是先从XML里把纯JSON字符串抽出来,再按照普通JSON的方式解析,不要想着一步到位解析这种混合格式,分开处理会简单很多。
内容的提问来源于stack exchange,提问作者John
相关产品推荐
相关产品推荐

