SingleValueEncodingContainerとKeyedEncodingContainerでEncodableを型に持つ変数をエンコードする時の挙動の違いについて(KeyedEncodingContainerだとエラーが出る)
swift初心者です。
let foo: Encodable
などのEncodableの型を持つ変数をJSONEncoderでエンコードしたいです。
調べたところ、https://forums.swift.org/t/how-to-encode-objects-of-unknown-type/12253
のサイトより、
import Foundation
extension Encodable {
fileprivate func encode(to container: inout SingleValueEncodingContainer) throws {
try container.encode(self)
}
}
struct AnyEncodable1 : Encodable {
var value: Encodable
init(_ value: Encodable) {
self.value = value
}
func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
try value.encode(to: &container)
}
}
struct MyThing : Encodable {
let myURL = AnyEncodable1(URL(string: "http://swift.org")!)
}
let url = URL(string: "http://swift.org")
let encoder = JSONEncoder()
var data = try encoder.encode(MyThing())
とするとEncodableの変数もエンコードできることがわかりました。
しかし、このコードだとEncodableをAnyEncodable1つにつき1個しか保存できません。
そこで、
extension Encodable {
fileprivate func encode<K>(to container: inout KeyedEncodingContainer<K>, for key: CodingKey {
try container.encode(self, forKey: key)
// error: Cannot invoke 'encode' with an argument list of type '(Self, forKey: CodingKey)'
}
}
struct AnyEncodable1 : Encodable {
var value: Encodable
init(_ value: Encodable) {
self.value = value
}
enum CodingKeys: String, CodingKey {
case value
}
func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try value.encode(to: &container, for: .value)
}
}
struct MyThing : Encodable {
let myURL = AnyEncodable1(URL(string: "http://swift.org")!)
}
let url = URL(string: "http://swift.org")
let encoder = JSONEncoder()
var data = try encoder.encode(MyThing())
というようにSingleValueEncodingContainerをKeyedEncodingContainerに入れ替えました。しかし、入れ替えると先程までは出ていなかったエラーが出ました。
SingleValueEncodingContainerとKeyedEncodingContainerのencodeメソッドの宣言はそれぞれ
// SingleValueEncodingContainer
mutating func encode<T>(_ value: T) throws where T : Encodable
// KeyedEncodingContainer
mutating func encode<T>(_ value: T, forKey key: KeyedEncodingContainer.Key) throws where T : Encodable
とKeyedEncodingContainerにはキーが必要だということ以外は変わりません。
しかし、なぜKeyedEncodingContainerではエラーが出るのでしょうか。
ちなみにUnkeyedEncodingContainerに入れ替えるとエラーは出ませんでした。
なぜこのようになるか理由を教えていただけると幸いです。
よろしくお願い致します。
swift4、xcode9.2です。