iOS swift Codable不能与Alamofire一起使用的JSON嵌套数据吗?

问题描述 投票:0回答:1

我是Alamofire和Codable概念的新手,有人可以告诉我如何使用它来访问我的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)

            }
    }
}

有人可以帮我用codable访问嵌套数组数据吗?预先感谢。

ios swift alamofire codable
1个回答
2
投票

您缺少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格式。

要在用户界面中显示日期,您需要执行以下操作:

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

然后:

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

在美国讲英语的人会看到:

2019年4月15日

驻美国的讲西班牙语的人将会看到:

abr。 2019年15月15日

在西班牙讲西班牙语的人将会看到:

2019年4月15日

底线,用户将以他们期望的格式看到日期,而不是以某些特定的美国英语格式进行硬编码。另外,您还可以选择在空间允许的情况下使用.long格式(例如,“ 2019年4月15日”),或者在空间有限的情况下使用.short格式(例如“ 04/15/19”)。只需选择适合您特定需求的dateStyle

© www.soinside.com 2019 - 2024. All rights reserved.