Swift - 解码数组 JSON 数据的数组
Swift - Decode array of an arrays JSON data
我正在使用 Swift 5,我正在尝试创建一个结构来保存 Google Sheets API 调用的内容。
我被 "values" 键困住了,我想获取哪些值,更改为 Int 类型并存储在我最近可以使用的单独的数组变量中。
这是 API 的一个结果:
{
"range": "Sheet1!A2:B4",
"majorDimension": "ROWS",
"values": [
[
"-10",
"12"
],
[
"-9",
"-15"
],
[
"-8",
"-9"
]
[
"-7",
"4"
]
]
}
在我以前的方法中我得到了一个错误:"Expected to decode String but found an array instead."
所以我的问题是 "values" 的内部结构应该如何完成任务?
struct Sheet: Decodable {
let range: String?
let majorDimension: String?
let values: [Values]?
}
do {
let json = try JSONDecoder().decode(Sheet.self, from: data)
} catch let error {
print(error as Any)
}
谢谢!
您发布的 JSON 无效(缺少逗号),但是当您修复它时,使用
时它可以解析
struct Sheet: Decodable {
let range, majorDimension: String
let values: [[String]]
}
即通过使 values
成为字符串的二维数组。
要将值转换为所需的 Int
值,您可以提供访问器:
extension Sheet {
var intValues: [[Int]] {
return values.map {
[=11=].compactMap { Int([=11=]) }
}
}
}
请注意,您的 JSON 在此数组后缺少一个逗号:
[
"-8",
"-9"
]
假设你修复了这个问题,你需要创建 values
[[String]]?
的类型:
struct Response: Codable {
// you don't actually need optional properties if you are sure they exist
let range: String?
let majorDimension: String?
let values: [[String]]?
// you don't need CodingKeys here since all your property names match the JSON keys
}
如果您希望数字为 Double
s,您可以这样做(假设数字始终有效):
struct Response: Codable {
let range: String?
let majorDimension: String?
let values: [[Double]]?
// now you need CodingKeys, but you don't need to give them raw values
enum CodingKeys: String, CodingKey {
case range
case majorDimension
case values
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
range = try container.decodeIfPresent(String.self, forKey: .range)
majorDimension = try container.decodeIfPresent(String.self, forKey: .majorDimension)
// use map to transform the strings to doubles
values = try container.decodeIfPresent([[String]].self, forKey: .values)?
.map { [=12=].map { Double([=12=])! } }
// or if you want to filter out the invalid numbers...
// .map { [=12=].compactMap(Double.init) }
}
}
我正在使用 Swift 5,我正在尝试创建一个结构来保存 Google Sheets API 调用的内容。 我被 "values" 键困住了,我想获取哪些值,更改为 Int 类型并存储在我最近可以使用的单独的数组变量中。
这是 API 的一个结果:
{
"range": "Sheet1!A2:B4",
"majorDimension": "ROWS",
"values": [
[
"-10",
"12"
],
[
"-9",
"-15"
],
[
"-8",
"-9"
]
[
"-7",
"4"
]
]
}
在我以前的方法中我得到了一个错误:"Expected to decode String but found an array instead."
所以我的问题是 "values" 的内部结构应该如何完成任务?
struct Sheet: Decodable {
let range: String?
let majorDimension: String?
let values: [Values]?
}
do {
let json = try JSONDecoder().decode(Sheet.self, from: data)
} catch let error {
print(error as Any)
}
谢谢!
您发布的 JSON 无效(缺少逗号),但是当您修复它时,使用
时它可以解析struct Sheet: Decodable {
let range, majorDimension: String
let values: [[String]]
}
即通过使 values
成为字符串的二维数组。
要将值转换为所需的 Int
值,您可以提供访问器:
extension Sheet {
var intValues: [[Int]] {
return values.map {
[=11=].compactMap { Int([=11=]) }
}
}
}
请注意,您的 JSON 在此数组后缺少一个逗号:
[
"-8",
"-9"
]
假设你修复了这个问题,你需要创建 values
[[String]]?
的类型:
struct Response: Codable {
// you don't actually need optional properties if you are sure they exist
let range: String?
let majorDimension: String?
let values: [[String]]?
// you don't need CodingKeys here since all your property names match the JSON keys
}
如果您希望数字为 Double
s,您可以这样做(假设数字始终有效):
struct Response: Codable {
let range: String?
let majorDimension: String?
let values: [[Double]]?
// now you need CodingKeys, but you don't need to give them raw values
enum CodingKeys: String, CodingKey {
case range
case majorDimension
case values
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
range = try container.decodeIfPresent(String.self, forKey: .range)
majorDimension = try container.decodeIfPresent(String.self, forKey: .majorDimension)
// use map to transform the strings to doubles
values = try container.decodeIfPresent([[String]].self, forKey: .values)?
.map { [=12=].map { Double([=12=])! } }
// or if you want to filter out the invalid numbers...
// .map { [=12=].compactMap(Double.init) }
}
}