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

Swift中JSON解码失败:给定数据非有效JSON问题排查

问题解决:Swift JSONDecoder解码API返回数据失败

问题背景

调用指定API后,使用JSONDecoder解码Dashboardd模型时触发数据损坏错误,提示The given data was not valid JSON。

API调用代码

@State private var receives = [Advertisment]()
func loadData() async {

    guard let url = URL(string: "https://new.demozab.com/armup/api/public/api/dashboard")
    else{
        print("iii")
        return
    }

    var request = URLRequest(url: url)

    request.setValue("U45GxRbn6NLY9Q3QomfgdWpePAjnlTE7O05wPIXL", forHTTPHeaderField: "Authorization")

    do{
        let (data,_) = try await URLSession.shared.data(from: url)
        print(data.count)
        print("\(data)")
         let decodedResponse =  try JSONDecoder().decode(Dashboardd.self, from: data)

        print("klllll")
        receives = (decodedResponse.data.advertisments )
        print(receives)
    }
    catch{
        print("\(error)")
    }
}

模型类代码

struct Dashboardd: Codable {
    let success: Bool
    let message: String
    let data: DashboardDataClass
}

// MARK: - DataClass
struct DashboardDataClass: Codable {
    let quickStats: QuickStats
    let advertisments: [Advertisment]
    let receives: [Receive]
}

// MARK: - Advertisment
struct Advertisment: Codable {
    let id, cryptoCurrencyID, tradeBy: Int
    let tradeType, location, country, market: String
    let margin: String
    let tradePrice: Double
    let tradeTotal, minTransactionLimit, maxTransactionLimit, totalLimit: Int
    let totalTradeAmount, cryptoCoinAmountPrice, paymentWindow: Int
    let paymentMethod, accountDetails, additionalInformation, terms: String
    let isFeedback, status: Int
    let createdAt, updatedAt, slug: String

    enum CodingKeys: String, CodingKey {
        case id
        case cryptoCurrencyID
        case tradeBy
        case tradeType
        case location, country, market, margin
        case tradePrice
        case tradeTotal
        case minTransactionLimit
        case maxTransactionLimit
        case totalLimit
        case totalTradeAmount
        case cryptoCoinAmountPrice
        case paymentWindow
        case paymentMethod
        case accountDetails
        case additionalInformation
        case terms
        case isFeedback
        case status
        case createdAt
        case updatedAt
        case slug
    }
}

// MARK: - QuickStats
struct QuickStats: Codable {
    let buyCnt, sellCnt, openCnt, pendingCnt: Int
    let completeCnt: Int
}

// MARK: - Receive
struct Receive: Codable {
    let id, tradeOrderID, senderID, receiverID: Int
    let isTrustedUser, isDistrustedUser, feedbackScore: Int
    let message: String
    let status: Int
    let createdAt, updatedAt, username: String
    let image: String

    enum CodingKeys: String, CodingKey {
        case id
        case tradeOrderID
        case senderID
        case receiverID
        case isTrustedUser
        case isDistrustedUser
        case feedbackScore
        case message, status
        case createdAt
        case updatedAt
        case username, image
    }
}

接口返回JSON

{
    "success": true,
    "message": "Dashboard details",
    "data": {
        "quickStats": {
            "buyCnt": 3,
            "sellCnt": 0,
            "openCnt": 0,
            "pendingCnt": 0,
            "completeCnt": 1
        },
        "advertisments": [
            {
                "id": 8,
                "crypto_currency_id": 7,
                "trade_by": 4,
                "trade_type": "1",
                "location": "mdu",
                "country": "1",
                "market": "5",
                "margin": "15",
                "trade_price": 10,
                "trade_total": 0,
                "min_transaction_limit": 1,
                "max_transaction_limit": 16,
                "total_limit": 16,
                "total_trade_amount": 0,
                "crypto_coin_amount_price": 0,
                "payment_window": 1,
                "payment_method": "a",
                "account_details": "d",
                "additional_information": "d",
                "terms": "mm",
                "is_feedback": 0,
                "status": 0,
                "created_at": "2023-02-15",
                "updated_at": "2023-02-15T05:31:12.000000Z",
                "slug": ""
            },
            {
                "id": 5,
                "crypto_currency_id": 1,
                "trade_by": 4,
                "trade_type": "Buy",
                "location": "demo",
                "country": "98",
                "market": "74",
                "margin": "1.2",
                "trade_price": 15375.35,
                "trade_total": 0,
                "min_transaction_limit": 100,
                "max_transaction_limit": 1000,
                "total_limit": 1000,
                "total_trade_amount": 0,
                "crypto_coin_amount_price": 0,
                "payment_window": 15,
                "payment_method": "1",
                "account_details": "demo",
                "additional_information": "demo",
                "terms": "demo",
                "is_feedback": 0,
                "status": 0,
                "created_at": "2023-01-28",
                "updated_at": "2023-01-28T14:42:52.000000Z",
                "slug": "BTC"
            },
            {
                "id": 4,
                "crypto_currency_id": 1,
                "trade_by": 4,
                "trade_type": "Buy",
                "location": "demo",
                "country": "98",
                "market": "98",
                "margin": "1.2",
                "trade_price": 1254583.09,
                "trade_total": 0,
                "min_transaction_limit": 10,
                "max_transaction_limit": 100,
                "total_limit": 100,
                "total_trade_amount": 0,
                "crypto_coin_amount_price": 0,
                "payment_window": 15,
                "payment_method": "1",
                "account_details": "demo",
                "additional_information": "demo",
                "terms": "demo",
                "is_feedback": 0,
                "status": 0,
                "created_at": "2023-01-28",
                "updated_at": "2023-01-28T14:02:46.000000Z",
                "slug": "BTC"
            },
            {
                "id": 3,
                "crypto_currency_id": 3,
                "trade_by": 4,
                "trade_type": "Buy",
                "location": "demo",
                "country": "22",
                "market": "102",
                "margin": "1.2",
                "trade_price": 0.89,
                "trade_total": 0,
                "min_transaction_limit": 10,
                "max_transaction_limit": 100,
                "total_limit": 100,
                "total_trade_amount": 0,
                "crypto_coin_amount_price": 0,
                "payment_window": 15,
                "payment_method": "1",
                "account_details": "demo",
                "additional_information": "demo",
                "terms": "demo",
                "is_feedback": 0,
                "status": 0,
                "created_at": "2023-01-28",
                "updated_at": "2023-01-28T14:00:59.000000Z",
                "slug": "BUSD"
            }
        ],
        "receives": [
            {
                "id": 7,
                "trade_order_id": 11,
                "sender_id": 4,
                "receiver_id": 4,
                "is_trusted_user": 1,
                "is_distrusted_user": 0,
                "feedback_score": 4,
                "message": "test",
                "status": 1,
                "created_at": "2023-01-28T14:27:04.000000Z",
                "updated_at": "2023-02-23T05:23:02.000000Z",
                "username": "smith",
                "image": "https://new.demozab.com/armup/api/public//userpanel/images/profile.svg"
            }
        ]
    }
}

错误信息

dataCorrupted(Swift.DecodingError.Context(codingPath: [], debugDescription: "The given data was not valid JSON.", underlyingError: Optional(Error Domain=NSCocoaErrorDomain Code=3840 "Invalid value around line 1, column 0." UserInfo={NSDebugDescription=Invalid value around line 1, column 0., })))

解决步骤

1. 修复API请求的使用错误

你创建了带Authorization头的URLRequest,但实际调用时没有使用这个请求,而是直接用了原始URL。这会导致API返回非JSON数据(比如401错误页面),从而触发JSON无效的错误。修改代码:

// 替换data(from: url)为data(for: request)
let (data,_) = try await URLSession.shared.data(for: request)

2. 修正模型类的键映射

模型类的CodingKeys没有正确对应JSON中的蛇形命名键(比如模型的cryptoCurrencyID对应JSON的crypto_currency_id),导致解码失败。有两种解决方式:

  • 手动设置CodingKeys:给每个驼峰命名的属性添加对应的蛇形键值,示例:
enum CodingKeys: String, CodingKey {
    case id
    case cryptoCurrencyID = "crypto_currency_id"
    case tradeBy = "trade_by"
    // 其他属性依次补充对应映射
}
  • 自动转换键格式:给JSONDecoder设置keyDecodingStrategy,自动将蛇形键转为驼峰命名,无需手动编写CodingKeys:
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
let decodedResponse = try decoder.decode(Dashboardd.self, from: data)

3. 可选:添加调试打印

在解码前将返回数据转为字符串打印,方便确认API返回的是否为有效JSON:

if let jsonString = String(data: data, encoding: .utf8) {
    print("API返回内容:\n\(jsonString)")
}

完整修正后的API调用代码

@State private var receives = [Advertisment]()
func loadData() async {
    guard let url = URL(string: "https://new.demozab.com/armup/api/public/api/dashboard") else {
        print("无效URL")
        return
    }

    var request = URLRequest(url: url)
    request.setValue("U45GxRbn6NLY9Q3QomfgdWpePAjnlTE7O05wPIXL", forHTTPHeaderField: "Authorization")

    do {
        let (data, _) = try await URLSession.shared.data(for: request)
        
        // 调试用:打印返回的JSON字符串
        if let jsonString = String(data: data, encoding: .utf8) {
            print("API返回JSON:\n\(jsonString)")
        }
        
        let decoder = JSONDecoder()
        decoder.keyDecodingStrategy = .convertFromSnakeCase
        let decodedResponse = try decoder.decode(Dashboardd.self, from: data)
        
        receives = decodedResponse.data.advertisments
        print("解码成功,广告数据:\(receives)")
    } catch {
        print("解码错误:\(error)")
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 20:27:19