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

Swift POST请求报错:Invalid type in JSON write问题求助

Swift调用机器学习API报错排查(Postman正常,Xcode崩溃)

问题场景

调用https://doctagon.herokuapp.com/diagnose的POST接口时,Postman发送请求可正常返回结果,但Swift实现的代码触发崩溃,错误提示为Invalid type in JSON write (Foundation.__NSSwiftData)。

原请求代码

func makePOSTRequest() {
        
        print("entered request function")
        
        guard let url = URL(string: "https://doctagon.herokuapp.com/diagnose") else {
            print("error with getting the URL")
            return
        }
        print("got the URL")
        
        var request = URLRequest(url: url)
        print("Got the request")
        // method, body, headers?
        request.httpMethod = "POST"
        print("got the http.method = 'POST'")
        
        // might not need this --> request.setValue(" symptoms", forHTTPHeaderField: "Content-Type")
        let body: [String: AnyHashable] = [
            "symptoms": ["Headache", "Sweating"]
        ]
        print("got the body")
        
        print("About to enter the .httpBody part of the code")
        request.httpBody = try? JSONSerialization.data(withJSONObject: body, options: .fragmentsAllowed)
        //Make the request
        let task = URLSession.shared.dataTask(with: request) { data, _, error in
            guard let data = data, error == nil else {
                print("error with making sure that there is data")
                return
            }
            print("got data")
            do {
                let response = try JSONSerialization.data(withJSONObject: data, options: .fragmentsAllowed)
                print("SUCCESS \(response)")
            } catch {
                print("error with the conversion of the JSOn")
                print(error)
            }
        }
        task.resume()
        print("resumed Task")
    }

错误日志

2022-11-19 23:39:30.335160-0500 Doctagon[88188:1838200] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Invalid type in JSON write (Foundation.__NSSwiftData)'
*** First throw call stack:
(
    0   CoreFoundation                      0x000000018040e7ec __exceptionPreprocess + 172
    1   libobjc.A.dylib                     0x0000000180051144 objc_exception_throw + 56
    2   Foundation                          0x0000000180c446f8 _writeJSONValue + 704
    3   Foundation                          0x0000000180c443f8 -[_NSJSONWriter dataWithRootObject:options:] + 84
    4   Foundation                          0x0000000180c470d0 +[NSJSONSerialization dataWithJSONObject:options:error:] + 108
    5   Doctagon                            0x0000000100be4080 $s8Doctagon12QuestionViewV15makePOSTRequestyyFy10Foundation4DataVSg_So13NSURLResponseCSgs5Error_pSgtYbcfU_ + 544
    6   Doctagon                            0x0000000100be45ec $s10Foundation4DataVSgSo13NSURLResponseCSgs5Error_pSgIeghggg_So6NSDataCSgAGSo7NSErrorCSgIeyBhyyy_TR + 264
    7   CFNetwork                           0x0000000183df9928 CFNetwork + 31016
    8   CFNetwork                           0x0000000183e14a4c _CFHTTPMessageSetResponseProxyURL + 14648
    9   libdispatch.dylib                   0x0000000104c30594 _dispatch_call_block_and_release + 24
    10  libdispatch.dylib                   0x0000000104c31d5c _dispatch_client_callout + 16
    11  libdispatch.dylib                   0x0000000104c3a040 _dispatch_lane_serial_drain + 928
    12  libdispatch.dylib                   0x0000000104c3adb8 _dispatch_lane_invoke + 484
    13  libdispatch.dylib                   0x0000000104c48b40 _dispatch_workloop_worker_thread + 1720
    14  libsystem_pthread.dylib             0x00000001af2568fc _pthread_wqthread + 284
    15  libsystem_pthread.dylib             0x00000001af2556c0 start_wqthread + 8
)
libc++abi: terminating with uncaught exception of type NSException
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Invalid type in JSON write (Foundation.__NSSwiftData)'
terminating with uncaught exception of type NSException
CoreSimulator 857.13 - Device: iPhone 14 Pro (4108291D-D836-4715-8386-5237B6D217E7) - Runtime: iOS 16.1 (20B72) - DeviceType: iPhone 14 Pro

错误原因

  1. 核心错误:处理API返回数据时,错误调用了JSONSerialization.data(withJSONObject: data, ...)——该方法的作用是将JSON对象(字典/数组)转成二进制数据,但你传入的data本身就是API返回的二进制数据,类型不匹配直接触发崩溃。正确做法是用JSONSerialization.jsonObject(with: data, ...)把二进制数据解析成JSON对象。
  2. 次要问题:请求未设置Content-Type: application/json头,Postman会自动添加该头,但Swift中如果不设置,服务器可能无法正确解析请求体;另外try?处理请求体序列化会默默失败,无法排查序列化错误。

修正后的代码

func makePOSTRequest() {
    print("entered request function")
    
    guard let url = URL(string: "https://doctagon.herokuapp.com/diagnose") else {
        print("error with getting the URL")
        return
    }
    print("got the URL")
    
    var request = URLRequest(url: url)
    request.httpMethod = "POST"
    // 必须设置Content-Type,告诉服务器请求体是JSON格式
    request.setValue("application/json", forHTTPHeaderField: "Content-Type")
    
    let body: [String: Any] = [
        "symptoms": ["Headache", "Sweating"]
    ]
    
    do {
        // 用do-catch处理序列化错误,避免默默失败
        request.httpBody = try JSONSerialization.data(withJSONObject: body, options: [])
    } catch {
        print("Failed to serialize request body: \(error)")
        return
    }
    
    let task = URLSession.shared.dataTask(with: request) { data, _, error in
        guard let data = data, error == nil else {
            print("Request error: \(error ?? NSError(domain: "UnknownError", code: -1, userInfo: nil))")
            return
        }
        print("got data")
        
        do {
            // 正确解析返回的JSON数据为对象(字典/数组)
            let responseObject = try JSONSerialization.jsonObject(with: data, options: .allowFragments)
            print("SUCCESS: \(responseObject)")
            // 可选:转成字符串查看原始返回内容
            if let jsonString = String(data: data, encoding: .utf8) {
                print("JSON String: \(jsonString)")
            }
        } catch {
            print("Failed to parse response JSON: \(error)")
            // 排查用:查看原始返回的字符串形式
            if let rawString = String(data: data, encoding: .utf8) {
                print("Raw response: \(rawString)")
            }
        }
    }
    task.resume()
    print("resumed Task")
}

内容的提问来源于stack exchange,提问作者Anish

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 07:05:32