【发布时间】:2020-03-29 18:09:43
【问题描述】:
如何为 primitive 类型(如 Int、Bool)自定义 JSONDecoder 的行为?
问题来了:
-
类型不能依赖后端。例如:Bool 可以是 true/false 或 "true"/"false"(bool 可以用双引号括起来)
-
我们至少有 300 个 Codable 结构,其中平均有 15 个属性,编写解码逻辑很麻烦。此外,逻辑或多或少保持不变,因此代码变得重复
因此我正在寻找一种解决方案,如果有 Type mismatch 原始类型应该能够处理它,如果没有,那么它应该设置为 nil,前提是该类型是可选的。
为此我尝试了多种方法
1。在所有原始类型上使用 Wrapper 并处理解码逻辑。以下是 Bool 上的包装器示例
struct Bool1: Codable{
private var bool: Bool?
public init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
if let b = try? container.decode(Bool.self) {
self.bool = b
} else if let string = try? container.decode(String.self) {
if string.lowercased() == "true" {
self.bool = true
} else if string.lowercased() == "false" {
self.bool = false
} else {
throw Error()
}
}
}
}
但这在其他开发人员中造成了不必要的混淆,因为 Wrapped 类型不像 Native 类型那样自然地出现。此外,无法直接访问该值(它总是需要 xyz.bool)来提取原始值
2。创建一个继承自 Decodable 和子类 JSONDecoder 的新协议
protocol KKDecodable: Decodable {
init(decoder1: Decoder)
}
extension Bool: KKDecodable {
init(decoder1: Decoder) {
// Logic for creating Bool from different types
}
}
class JSONDecoder1: JSONDecoder {
func decode<T>(_ type: T.Type, from data: Data) throws -> T where T : KKDecodable {
// Some code that would invoke `init(decoder1: Decoder)`
// which is defined in `KKDecodable`
}
}
我无法使用这种方法编写工作代码
【问题讨论】:
-
这个怎么样? stackoverflow.com/a/46850257/562298(为您的自定义类型创建一个自定义包装器,然后添加一个调用 xyz.bool 的计算属性,因此开发人员无需混淆。)
-
是的。这就是我现在实施的解决方案。但它有一些缺点。 1. 所有的开发者都需要使用封装类型,看起来不直观 2. 所有的变量都需要额外的函数来提取实际值。
-
类型不能依赖后端。 为什么?这是荒谬的。出于性能原因,后端应该做出努力,而不是前端。
-
我想
JSONSerialization在你的情况下不起作用?
标签: swift jsondecoder