【发布时间】:2017-05-05 09:31:06
【问题描述】:
我使用Decodable 从 JSON 解码一个简单的结构。这通过遵守Decodable 协议来工作:
extension BackendServerID: Decodable {
static func decode(_ json: Any) throws -> BackendServerID {
return try BackendServerID(
id: json => "id",
name: json => "name"
)
}
}
不过,我希望能够使用String 拨打decode,所以我添加了一个分机:
extension Decodable {
static func decode(_ string: String) throws -> Self {
let jsonData = string.data(using: .utf8)!
let jsonObject = try JSONSerialization.jsonObject(with: jsonData, options: [])
return try decode(jsonObject)
}
}
然后我想像这样解码对象:
XCTAssertNoThrow(try BackendServerID.decode("{\"id\": \"foo\", \"name\": \"bar\"}"))
但这并没有按预期工作,因为不知何故调用了 decode(Any) 方法而不是 decode(String)。我究竟做错了什么? (当我通过将自定义方法重命名为 decodeString 来澄清调用时,它可以正常工作。)
【问题讨论】:
-
如何将
decode(_ string: String)重命名为decode(string: String)并显式调用BackendServerID.decode(string: "...")? -
谢谢!这会行得通,但我还是希望类型系统为我找出参数类型。
-
考虑使用Swift3 naming conventions,在每个弱类型参数前加上一个描述其作用的名词,例如:
static func decode(string: String) -
我不想涉及命名参数(老实说!),但在这种情况下,我认为参数名称没有太多需要澄清的地方——显然是要解码的东西。有关类似情况,请参阅UserDefaults。那里的
set方法都没有在第一个参数名称前加上它的类型。 -
您可能误读了命名约定?再次阅读其示例并将其与 UserDefaults 进行比较。 UserDefaults 尊重它及其所有
set方法,与约定示例几乎相同。 UserDefault 的set方法不需要精确第一个参数标签,因为Bool无法解析为String。在你的情况下,String可以解析为Any,那么如果你给他一个String作为第一个参数,编译器很难知道他是否应该调用decode(Any)或decode(String)。
标签: json swift overloading