在 Swift 中将 JSONEncoder 用于 Equatable 方法
Using JSONEncoder for Equatable method in Swift
我知道 JSON 键没有任何顺序,可以随机生成,但没有任何东西阻止我编写这个函数,而且从我的测试来看,它适用于我测试的每个用例.
func ==<T: Encodable> (lhs: T, rhs: T) -> Bool {
let encoder = JSONEncoder()
do {
let leftEncoded = try encoder.encode(lhs)
let rightEncoded = try encoder.encode(rhs)
return leftEncoded == rightEncoded
} catch {
return false
}
}
我想解决的问题是为一种类型编写一个函数,该类型具有一个协议的数组,具有大约 20 种不同的实现,我必须实现 ==
函数而不是 swift自动合成。而且我知道我可以使用选项 .sortedKeys
切换到 JSONSerialization.writeJSONObject
以保留键顺序。
与任何其他编写 ==
函数的方法相比,此实现的缺点是什么?
答案似乎在您的问题中:"JSON keys don't have any order."此外,两个逻辑上相等的事物可能编码不同(例如,如果它们的相等性仅取决于它们的 id)。此外,编码相同值的引用类型可能根本不相等(例如 UIView)。此外,这会创建一个非常广泛的 ==
重载,使类型检查更加昂贵(就像 +
非常昂贵)。
您正在做的是在可以合成时尝试自动符合 Equatable
。 Swift 本来可以做到的;事实上,对于大多数 Encodable
情况,只需添加 : Equatable
即可合成 Equatable
。 Swift 团队在这些情况下明确选择不自动符合并强制您在需要时提出要求,因为它并不总是意味着 "all the properties contain the same bits." 当 Swift 团队明确选择时为了避免一个功能,重新添加它很少是一个好主意。
func ==<T: Codable> (lhs: T, rhs: T) -> Bool {
let encoder = JSONEncoder()
guard let lhsData = try? encoder.encode(lhs),
let rhsData = try? encoder.encode(lhs),
let left = try? JSONSerialization.jsonObject(with: lhsData) as? [String : Any],
let right = try? JSONSerialization.jsonObject(with: rhsData) as? [String : Any] else { return false }
let leftDictionary = left as NSDictionary
let rightDictionary = right
return leftDictionary.isEqual(to: rightDictionary)
}
我知道 JSON 键没有任何顺序,可以随机生成,但没有任何东西阻止我编写这个函数,而且从我的测试来看,它适用于我测试的每个用例.
func ==<T: Encodable> (lhs: T, rhs: T) -> Bool {
let encoder = JSONEncoder()
do {
let leftEncoded = try encoder.encode(lhs)
let rightEncoded = try encoder.encode(rhs)
return leftEncoded == rightEncoded
} catch {
return false
}
}
我想解决的问题是为一种类型编写一个函数,该类型具有一个协议的数组,具有大约 20 种不同的实现,我必须实现 ==
函数而不是 swift自动合成。而且我知道我可以使用选项 .sortedKeys
切换到 JSONSerialization.writeJSONObject
以保留键顺序。
与任何其他编写 ==
函数的方法相比,此实现的缺点是什么?
答案似乎在您的问题中:"JSON keys don't have any order."此外,两个逻辑上相等的事物可能编码不同(例如,如果它们的相等性仅取决于它们的 id)。此外,编码相同值的引用类型可能根本不相等(例如 UIView)。此外,这会创建一个非常广泛的 ==
重载,使类型检查更加昂贵(就像 +
非常昂贵)。
您正在做的是在可以合成时尝试自动符合 Equatable
。 Swift 本来可以做到的;事实上,对于大多数 Encodable
情况,只需添加 : Equatable
即可合成 Equatable
。 Swift 团队在这些情况下明确选择不自动符合并强制您在需要时提出要求,因为它并不总是意味着 "all the properties contain the same bits." 当 Swift 团队明确选择时为了避免一个功能,重新添加它很少是一个好主意。
func ==<T: Codable> (lhs: T, rhs: T) -> Bool {
let encoder = JSONEncoder()
guard let lhsData = try? encoder.encode(lhs),
let rhsData = try? encoder.encode(lhs),
let left = try? JSONSerialization.jsonObject(with: lhsData) as? [String : Any],
let right = try? JSONSerialization.jsonObject(with: rhsData) as? [String : Any] else { return false }
let leftDictionary = left as NSDictionary
let rightDictionary = right
return leftDictionary.isEqual(to: rightDictionary)
}