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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 08:09:49