簡體   English   中英

iOS swift Codable 不適用於 JSON 嵌套數據的 Alamofire?

[英]iOS swift Codable not working with Alamofire for JSON nested data?

我是 Alamofire 和 Codable 概念的新手在 iOS 中,有人可以告訴我如何使用它來訪問我的 json 數據。

這是我的 json 回復。

{"subscriptions": [
        {
            "batch_user_id": 23,
            "batch_name": "demo batch",
            "course_name": "IELTS",
            "start_date": "Nov 01 2019",
            "end_date": "Nov 30 2019",
            "no_of_days": 21,
            "total_no_of_days": 30,
            "extended_date": "Nov 30 2019",
            "extended": false,
            "course_extensions": [
                {
                    "id": 31,
                    "amount": "3500.0",
                    "course_id": 1,
                    "is_active": true,
                    "number_of_days": 5
                },

這是可編碼的代碼:

 struct course_extensions: Codable {
        let id: String
        let amount: String
        let course_id: String

        private enum CodingKeys: String, CodingKey {
            case id = "id"
            case amount = "amount"
            case course_id = "course_id"
        }
    }

    struct subscriptions: Codable {
        let batch_user_id: String
        let batch_name: String
        let course_extensions: course_extensions

        private enum CodingKeys: String, CodingKey {
            case batch_user_id
            case batch_name
            case course_extensions = "course_extensions"
        }
    }
    struct User: Codable {
        let status: String
        let message: String
        let subscriptions: subscriptions
    }

這是我與 alamofire 的服務電話:

// MARK: - Service call

func fetchUserData() {
    AF.request(SMAConstants.my_subscriptions, method: .get, parameters: nil, headers: nil)
        .responseJSON { (response) in
            switch response.result {
            case .success(let value):
                let swiftyJsonVar = JSON(value)
                print(swiftyJsonVar)
            case .failure(let error):
                print(error)

            }
    }
}

有人可以幫我用可編碼的方式訪問嵌套數組數據嗎? 提前致謝。

您缺少 JSON 最外層部分的結構:

struct ResponseObject: Codable {
    let subscriptions: [Subscription]
}

而且,您可以使用普通的 camelCase 屬性:

struct Subscription: Codable {
    let batchUserId: Int
    let batchName: String
    let courseExtensions: [CourseExtension]
}

struct CourseExtension: Codable {
    let id: Int
    let amount: String
    let courseId: Int
    let isActive: Bool
}

幾點觀察:

  • 按照慣例, struct類型名稱應以大寫字母開頭。
  • 在這種情況下,這些CodingKeys不是必需的。
  • 小心你的類型。 其中一些是IntBool 僅當值在引號中時才使用String類型。
  • 顯然,為了簡潔起見,我從上述struct類型中排除了一些屬性,但添加了任何缺失的屬性,但堅持使用 camelCase 約定。

無論如何,您可以告訴解碼器將 snake_case JSON 鍵轉換為 camelCase 屬性名稱,使用:

do {
    let decoder = JSONDecoder()
    decoder.keyDecodingStrategy = .convertFromSnakeCase

    let object = try decoder.decode(ResponseObject.self, from: data)
    print(object.subscriptions)
} catch {
    print(error)
}

因此,例如,如果使用 Alamofire 5:

let decoder: JSONDecoder = {
    let decoder = JSONDecoder()
    decoder.keyDecodingStrategy = .convertFromSnakeCase
    return decoder
}()

func fetchUserData() {
    AF.request(SMAConstants.mySubscriptions))
        .responseDecodable(of: ResponseObject.self, decoder: decoder) { response in
            guard let value = response.value else {
                print(response.error ?? "Unknown error")
                return
            }

            print(value.subscriptions)
    }
}

這產生了:

[Subscription(batchUserId: 23, batchName: "demo batch", courseExtensions: [CourseExtension(id: 31, amount: "3500.0", courseId: 1, isActive: true)])]

順便說一句,我注意到您的日期格式為MMM d yyyy 您想將它們轉換為Date對象嗎? 如果是這樣,您可以使用指定日期格式化程序的解碼器,如下所示:

let decoder: JSONDecoder = {
    let decoder = JSONDecoder()

    decoder.keyDecodingStrategy = .convertFromSnakeCase

    let formatter = DateFormatter()
    formatter.locale = Locale(identifier: "en_US_POSIX")
    formatter.dateFormat = "MMM d yyyy"
    decoder.dateDecodingStrategy = .formatted(formatter)

    return decoder
}()

然后您可以將startDateendDate定義為Date對象。 然后,當您在 UI 中顯示這些日期時,您可以使用DateFormatter來顯示日期的良好本地化再現,而不僅僅是固定的、丑陋的MMM d yyyy格式。

要在 UI 中顯示日期,您需要執行以下操作:

let dateFormatter: DateFormatter = {
    let formatter = DateFormatter()
    formatter.dateStyle = .medium
    return formatter
}()

接着:

label.text = dateFormatter.string(from: date)

在美國講英語的人會看到:

2019 年 4 月 15 日

一位居住在美國的西班牙語人士將看到:

縮寫。 2019 年 15 月 15 日

在西班牙講西班牙語的人會看到:

2019 年 1 月 15 日

最重要的是,用戶將以他們期望的格式看到日期,而不是以某些特定的美國英語格式硬編碼。 您還可以選擇在空間允許的情況下使用.long格式(例如“2019 年 4 月 15 日”)或在空間非常緊張的情況下使用.short格式(例如“04/15/19”)。 只需選擇適合您特定需求的dateStyle

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM