Swift JSON 个全是数字名称的变量。解决办法是什么?
Swift JSON variables with all numeric names. What's the work around?
我正在提取一些需要使用 Decodable 解析的 JSON 数据到 Swift。
由于大部分数据是日期,因此我有 365 个日期条目:
"20170101": 0.17,
"20170102": 1.0,
"20170103": 0.68,
"20170104": 0.61,
"20170105": 1.03,
"20170106": 0.48,
"20170107": 0.52,
"20170108": 0.51,
"20170109": 0.28,
当我生成相关结构以吸收数据时,我如何创建一个看起来像是数字名称的变量:
var 20170101: Double
什么是数字名称的解决方法?
变量名不能以数字开头(尽管您可以在名称后面使用数字)。它们必须以字母或下划线开头 _
:
var _20170101: Double
var d20170101: Double
var d_20170101: Double
在 Swift 中(与其他语言一样)变量名称不能包含空白字符、数学符号(例如加号 (+) 或减号 (-) 运算符)或某些 Unicode 值或行和 box drawing characters。这样做的主要原因是为了确保 Swift 编译器能够理解变量名称的开始位置和结束位置。
除此之外,在命名变量时:
力求清晰
清晰优先于简洁
根据角色命名变量、参数和关联类型
有关命名约定的更多详细信息,请查看 here。
您可以将 json 字典解析为 [String:Double]
并将其转换为日期和双精度的元组数组:
let json = """
{
"20170101": 0.17,
"20170102": 1.0,
"20170103": 0.68,
"20170104": 0.61,
"20170105": 1.03,
"20170106": 0.48,
"20170107": 0.52,
"20170108": 0.51,
"20170109": 0.28
}
"""
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyyMMdd"
dateFormatter.locale = Locale(identifier: "en_US_POSIX")
do {
let array: [(date: Date, double: Double)] = try JSONDecoder().decode([String:Double].self, from: Data(json.utf8))
.compactMap({ key, value in
guard let date = dateFormatter.date(from: key) else { return nil }
return (date, value)
}).sorted(by: { [=12=].date < .date })
for (date, double) in array {
print("Date:", dateFormatter.string(from: date), "• Value:", double)
}
} catch {
print(error)
}
Date: 20170101 • Value: 0.17
Date: 20170102 • Value: 1.0
Date: 20170103 • Value: 0.68
Date: 20170104 • Value: 0.61
Date: 20170105 • Value: 1.03
Date: 20170106 • Value: 0.48
Date: 20170107 • Value: 0.52
Date: 20170108 • Value: 0.51
Date: 20170109 • Value: 0.28
我现在没有时间做一个编码答案,但与此同时你可以尝试在初始化程序中将你的字典解析为 [Date:Double
并设置
decoder.dateDecodingStrategy
在你的 JSONDecoder
中。我不确定 dateDecodingStrategy
是否适用于键,但似乎值得一试。查看 this post 以获取有关如何执行 dateDecodingStrategy
.
的更多详细信息
您不能使用数字作为属性名称的首字母。但有时我们必须使用您在代码中显示的数字。
该问题的解决方案是使用带有枚举的 CodingKey 协议,如下所示:
enum CodingKeys: String, CodingKey {
case date = "20170101" // You can use "date" instead of "20170101".
}
我正在提取一些需要使用 Decodable 解析的 JSON 数据到 Swift。
由于大部分数据是日期,因此我有 365 个日期条目:
"20170101": 0.17,
"20170102": 1.0,
"20170103": 0.68,
"20170104": 0.61,
"20170105": 1.03,
"20170106": 0.48,
"20170107": 0.52,
"20170108": 0.51,
"20170109": 0.28,
当我生成相关结构以吸收数据时,我如何创建一个看起来像是数字名称的变量:
var 20170101: Double
什么是数字名称的解决方法?
变量名不能以数字开头(尽管您可以在名称后面使用数字)。它们必须以字母或下划线开头 _
:
var _20170101: Double
var d20170101: Double
var d_20170101: Double
在 Swift 中(与其他语言一样)变量名称不能包含空白字符、数学符号(例如加号 (+) 或减号 (-) 运算符)或某些 Unicode 值或行和 box drawing characters。这样做的主要原因是为了确保 Swift 编译器能够理解变量名称的开始位置和结束位置。
除此之外,在命名变量时:
力求清晰
清晰优先于简洁
根据角色命名变量、参数和关联类型
有关命名约定的更多详细信息,请查看 here。
您可以将 json 字典解析为 [String:Double]
并将其转换为日期和双精度的元组数组:
let json = """
{
"20170101": 0.17,
"20170102": 1.0,
"20170103": 0.68,
"20170104": 0.61,
"20170105": 1.03,
"20170106": 0.48,
"20170107": 0.52,
"20170108": 0.51,
"20170109": 0.28
}
"""
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyyMMdd"
dateFormatter.locale = Locale(identifier: "en_US_POSIX")
do {
let array: [(date: Date, double: Double)] = try JSONDecoder().decode([String:Double].self, from: Data(json.utf8))
.compactMap({ key, value in
guard let date = dateFormatter.date(from: key) else { return nil }
return (date, value)
}).sorted(by: { [=12=].date < .date })
for (date, double) in array {
print("Date:", dateFormatter.string(from: date), "• Value:", double)
}
} catch {
print(error)
}
Date: 20170101 • Value: 0.17
Date: 20170102 • Value: 1.0
Date: 20170103 • Value: 0.68
Date: 20170104 • Value: 0.61
Date: 20170105 • Value: 1.03
Date: 20170106 • Value: 0.48
Date: 20170107 • Value: 0.52
Date: 20170108 • Value: 0.51
Date: 20170109 • Value: 0.28
我现在没有时间做一个编码答案,但与此同时你可以尝试在初始化程序中将你的字典解析为 [Date:Double
并设置
decoder.dateDecodingStrategy
在你的 JSONDecoder
中。我不确定 dateDecodingStrategy
是否适用于键,但似乎值得一试。查看 this post 以获取有关如何执行 dateDecodingStrategy
.
您不能使用数字作为属性名称的首字母。但有时我们必须使用您在代码中显示的数字。
该问题的解决方案是使用带有枚举的 CodingKey 协议,如下所示:
enum CodingKeys: String, CodingKey {
case date = "20170101" // You can use "date" instead of "20170101".
}