ios - 为什么即使我只需要自定义一个元素,我也必须添加样板文件才能使 Codable 工作?
问题描述
我Codable
在 Swift 中使用,对于超级简单的模型,我不必实现任何自定义解码代码,这很酷。像这样“有效”的东西:
struct Foo: Decodable {
let id: String
let name: String
let number: Double
}
但是,一旦发生不完美的事情,我需要实现 ENTIRECodingKeys
结构以及init(from decoder:)
.
例如,突然 API 将number
我想要表示为 Double 的字符串发回,这需要我添加所有这些样板文件。
// boilerplate CodingKeys
enum CodingKeys: String, CodingKey {
case id, name, number
}
init(from decoder: Decoder) throws {
// default boilerplate values
let values = try decoder.container(keyedBy: CodingKeys.self)
id = try values.decode(String.self, forKey: .id)
name = try values.decode(String.self, forKey: .name)
// Custom values
let numberString = try values.decode(String.self, forKey: .number)
number = Double(numberString) ?? 0
}
这很烦人,有几个原因:
- 一个自定义项目让我添加了所有这些额外的代码
- 我无法一眼看出哪些项目实际上是“自定义”的,哪些只是样板(当然,除非我以这种方式组织我的代码)
我只是对它为什么以这种方式建造感到困惑。是否存在需要使用此样板的技术限制?
当然,有没有办法避免这些样板文件?我看到的一个解决方案是创建一个numberDouble
可以使用字符串编号的不同变量,但这有点搞砸了命名。
解决方案
您可以使用计算属性解决您的问题。
只需制作一个“假”变量来保存您的字符串并使用自定义 CodingKey 对其进行解码。然后使用计算属性将“假”变量转换为 Double。
还有一些额外的代码行,但没有编写自定义解码器那么复杂。
struct Foo: Decodable {
let id: String
let name: String
private let numberString: String
enum CodingKeys: String, CodingKey {
case id
case name
case numberString = "number"
}
var number: Double {
Double(numberString) ?? 0
}
}
let json = """
{
"id":"1",
"name":"Mike",
"number":"12"
}
""".data(using: .utf8)!
let decoder = JSONDecoder()
let result = try! decoder.decode(Foo.self, from: json)
print(result.number)
推荐阅读
- java - 使用 apache kafka 的反应式和非阻塞方法 Micronaut
- vba - 删除一张图片
- reactjs - 如何在映射中返回 React 组件
- android - 精确定位所有屏幕尺寸和定义的视图
- reactjs - React UI 框架 VS 带有 styled-components 库的纯 CSS
- java - 通过多个不同的 xpath 查找元素
- javascript - Javascript:在模板文字中查找所有未转义的美元符号 ($)
- android - AdMob 仅展示测试广告
- java - 读取带空行的 int 文件并保存到数组 - JAVA
- python - Python 中的 Runtime.MarshalError