ios - Swift 5:解码嵌套JSON

标签 ios swift api networking struct

我在将一些JSON数据解码为结构时遇到了一些麻烦。我已经尝试过以下方法,但它不起作用:

JSON:

{
    "submission_date": "2020-02-28T14:21:46.000+08:00",
    "status": "pending",
    "requestor": {
        "name": "Adam"
    },
    "claim_items": [
        {
            "date": "2020-02-20",
            "description": "TV",
            "currency": "MYR",
            "amount": "103.0",
            "amount_in_ringgit": "10.0"
        },
        {
            "date": "2020-02-20",
            "description": "Netflix",
            "currency": "MYR",
            "amount": "12.0",
            "amount_in_ringgit": "10.0"
        }
    ]
}

结构方法1:
struct ClaimDetail: Decodable {
    let submission_date: String
    let status: String
    let requestor: Requestor
    let claim_items: [ClaimItem]
}

struct Requestor: Decodable {
    let name: String

    init(json: [String:Any]) {
        name = json["name"] as? String ?? ""
    }
}

struct ClaimItem: Decodable {
    let date: String
    let description: String
    let currency: String
    let amount: String
    let amount_in_ringgit: String

    init(json: [String:Any]) {
        date = json["date"] as? String ?? ""
        description = json["description"] as? String ?? ""
        currency = json["currency"] as? String ?? ""
        amount = json["amount"] as? String ?? ""
        amount_in_ringgit = json["amount_in_ringgit"] as? String ?? ""
    }
}

结构方法2:
struct ClaimDetail: Decodable {
    let submission_date: String
    let status: String
    let requestor: Requestor
    let claim_items: [ClaimItem]

    struct Requestor: Decodable {
        let name: String

        init(json: [String:Any]) {
            name = json["name"] as? String ?? ""
        }
    }

    struct ClaimItem: Decodable {
        let date: String
        let description: String
        let currency: String
        let amount: String
        let amount_in_ringgit: String

        init(json: [String:Any]) {
            date = json["date"] as? String ?? ""
            description = json["description"] as? String ?? ""
            currency = json["currency"] as? String ?? ""
            amount = json["amount"] as? String ?? ""
            amount_in_ringgit = json["amount_in_ringgit"] as? String ?? ""
        }
    }
}

结构方法3(通过https://app.quicktype.io/):
// MARK: - ClaimDetail
struct ClaimDetail: Codable {
    let submissionDate, status: String
    let requestor: Requestor
    let claimItems: [ClaimItem]

    enum CodingKeys: String, CodingKey {
        case submissionDate = "submission_date"
        case status, requestor
        case claimItems = "claim_items"
    }
}

// MARK: - ClaimItem
struct ClaimItem: Codable {
    let date, claimItemDescription, currency, amount: String
    let amountInRinggit: String

    enum CodingKeys: String, CodingKey {
        case date
        case claimItemDescription = "description"
        case currency, amount
        case amountInRinggit = "amount_in_ringgit"
    }
}

// MARK: - Requestor
struct Requestor: Codable {
    let name: String
}

URL session
URLSession.shared.dataTask(with: requestAPI) { [weak self] (data, response, error) in
    if let data = data {
        do {
            let json = try JSONDecoder().decode(ClaimDetail.self, from: data)
            print (json)
        } catch let error {
            print("Localized Error: \(error.localizedDescription)")
            print("Error: \(error)")
        }
    }
}.resume()

所有返回以下错误:

本地化错误:由于格式不正确,无法读取数据。
错误:dataCorrupted(Swift.DecodingError.Context(codingPath:[],debugDescription:“给定的数据不是有效的JSON。”,底层错误:可选(错误域= NSCocoaErrorDomain代码= 3840“字符0周围的值无效。” UserInfo = { NSDebugDescription =字符0周围的值无效。})))

最佳答案

解决方案:
我使用了struct方法#1,但这不是问题。问题在于我如何解码URLSession中的数据。由于某些原因,这可行:

URLSession.shared.dataTask(with: requestAPI) { [weak self] (data, response, error) in
    
    if let data = data {
    
        do {
            let dataString = String(data: data, encoding: .utf8)
            let jsondata = dataString?.data(using: .utf8)
            let result = try JSONDecoder().decode(ClaimDetail.self, from: jsondata!)
            print(result)
        
        } catch let error {
            print("Localized Error: \(error.localizedDescription)")
            print("Error: \(error)")
        }
    }
}.resume()
屏幕截图:
enter image description here
我不太了解,但我想我必须将数据转换为字符串,然后再对其进行解码?
谢谢大家的帮助。

关于ios - Swift 5:解码嵌套JSON,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60560581/

相关文章:

php - 如何使用定期计费功能设置 Paypal 自适应付款

ios - 保存 CLLocation 错误 : Mutating method sent to immutable object

ios - 克隆存储库并仍然从原始源获取更新?

ios - Firebase 真实数据库数据获取

ios - 线程 1 : signal SIGABRT ( Could not cast value of type )

nhibernate - nhibernate 的 api 引用在哪里?

c# - 是否有适用于 Salesforce REST Api 的 c# 包装器?

ios - Swift:获取用户的位置坐标作为纬度和经度?

ios - 如何在 Swift3 中使用分隔符连接 NSMutableArray 的对象

ios - 在 1 个 View Controller 中使用 2 个 uipickerview