iOS swift Codable 无法与 Alamofire 一起用于 JSON 嵌套数据?
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)
}
}
}
谁能帮我用 codable 访问嵌套数组数据。提前致谢。
您缺少 JSON 的最外层部分的结构:
struct ResponseObject: Codable {
let subscriptions: [Subscription]
}
而且,您可以使用普通的驼峰式属性:
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
不是必需的。
- 小心你的类型。其中一些是
Int
和 Bool
。如果值在引号中,则仅使用 String
类型。
- 显然,为了简洁起见,我从上面的
struct
类型中排除了一些属性,但添加了任何缺少的属性,但坚持驼峰命名法。
无论如何,您可以告诉解码器将 snake_case JSON 键转换为驼峰式 属性 名称,使用:
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
}()
然后你可以定义startDate
和endDate
为Date
对象。然后,当您在 UI 中显示这些日期时,您可以使用 DateFormatter
来显示日期的良好本地化再现,而不仅仅是固定的、丑陋的 MMM d yyyy
格式。
要在 UI 中显示日期,您需要执行以下操作:
let dateFormatter: DateFormatter = {
let formatter = DateFormatter()
formatter.dateStyle = .medium
return formatter
}()
然后:
label.text = dateFormatter.string(from: date)
在美国说英语的人会看到:
Apr 15, 2019
居住在美国的说西班牙语的人会看到:
abr. 15, 2019
在西班牙讲西班牙语的人会看到:
15 abr 2019
最重要的是,用户将以他们期望的格式看到日期,而不是以某种特定的美国英语格式进行硬编码。您还可以选择在 space 允许的情况下使用 .long
格式(例如“2019 年 4 月 15 日”),或者在您对 space 非常紧张的情况下使用 .short
格式(例如“04/15/19”)。只需选择适合您特定需求的 dateStyle
。
我是 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)
}
}
}
谁能帮我用 codable 访问嵌套数组数据。提前致谢。
您缺少 JSON 的最外层部分的结构:
struct ResponseObject: Codable {
let subscriptions: [Subscription]
}
而且,您可以使用普通的驼峰式属性:
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
不是必需的。 - 小心你的类型。其中一些是
Int
和Bool
。如果值在引号中,则仅使用String
类型。 - 显然,为了简洁起见,我从上面的
struct
类型中排除了一些属性,但添加了任何缺少的属性,但坚持驼峰命名法。
无论如何,您可以告诉解码器将 snake_case JSON 键转换为驼峰式 属性 名称,使用:
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
}()
然后你可以定义startDate
和endDate
为Date
对象。然后,当您在 UI 中显示这些日期时,您可以使用 DateFormatter
来显示日期的良好本地化再现,而不仅仅是固定的、丑陋的 MMM d yyyy
格式。
要在 UI 中显示日期,您需要执行以下操作:
let dateFormatter: DateFormatter = {
let formatter = DateFormatter()
formatter.dateStyle = .medium
return formatter
}()
然后:
label.text = dateFormatter.string(from: date)
在美国说英语的人会看到:
Apr 15, 2019
居住在美国的说西班牙语的人会看到:
abr. 15, 2019
在西班牙讲西班牙语的人会看到:
15 abr 2019
最重要的是,用户将以他们期望的格式看到日期,而不是以某种特定的美国英语格式进行硬编码。您还可以选择在 space 允许的情况下使用 .long
格式(例如“2019 年 4 月 15 日”),或者在您对 space 非常紧张的情况下使用 .short
格式(例如“04/15/19”)。只需选择适合您特定需求的 dateStyle
。