[英]How to encode a property with type of JSON dictionary in Swift 4 encodable protocol
Well, my question is simple. 好吧,我的问题很简单。 I want to do the same as this answer but for encode: How to decode a property with type of JSON dictionary in Swift 4 decodable protocol 我想做与此答案相同的操作,但要进行编码: 如何在Swift 4可解码协议中使用JSON字典类型解码属性
That solution works fine with decode, but I also need encode a Dictionary<String, Any>
该解决方案可以很好地与解码配合使用,但是我还需要对Dictionary<String, Any>
进行编码
I can't realize how to write the extension for KeyedEncodingContainer
and the other extensions, and what methods to write. 我不知道如何为KeyedEncodingContainer
和其他扩展编写扩展,以及编写什么方法。
You can do that by adapting the Decodable code snippet from that question's answer 您可以通过根据问题的答案改编可解码代码段来实现
extension KeyedEncodingContainerProtocol where Key == JSONCodingKeys {
mutating func encodeJSONDictionary(_ value: Dictionary<String, Any>) throws {
try value.forEach({ (key, value) in
let key = JSONCodingKeys(key: key)
switch value {
case let value as Bool:
try encode(value, forKey: key)
case let value as Int:
try encode(value, forKey: key)
case let value as String:
try encode(value, forKey: key)
case let value as Double:
try encode(value, forKey: key)
case let value as Dictionary<String, Any>:
try encode(value, forKey: key)
case let value as Array<Any>:
try encode(value, forKey: key)
case Optional<Any>.none:
try encodeNil(forKey: key)
default:
throw EncodingError.invalidValue(value, EncodingError.Context(codingPath: codingPath + [key], debugDescription: "Invalid JSON value"))
}
})
}
}
extension KeyedEncodingContainerProtocol {
mutating func encode(_ value: Dictionary<String, Any>, forKey key: Key) throws {
var container = self.nestedContainer(keyedBy: JSONCodingKeys.self, forKey: key)
try container.encodeJSONDictionary(value)
}
mutating func encodeIfPresent(_ value: Dictionary<String, Any>?, forKey key: Key) throws {
if let value = value {
try encode(value, forKey: key)
}
}
mutating func encode(_ value: Array<Any>, forKey key: Key) throws {
var container = self.nestedUnkeyedContainer(forKey: key)
try container.encodeJSONArray(value)
}
mutating func encodeIfPresent(_ value: Array<Any>?, forKey key: Key) throws {
if let value = value {
try encode(value, forKey: key)
}
}
}
extension UnkeyedEncodingContainer {
mutating func encodeJSONArray(_ value: Array<Any>) throws {
try value.enumerated().forEach({ (index, value) in
switch value {
case let value as Bool:
try encode(value)
case let value as Int:
try encode(value)
case let value as String:
try encode(value)
case let value as Double:
try encode(value)
case let value as Dictionary<String, Any>:
try encode(value)
case let value as Array<Any>:
try encode(value)
case Optional<Any>.none:
try encodeNil()
default:
let keys = JSONCodingKeys(intValue: index).map({ [ $0 ] }) ?? []
throw EncodingError.invalidValue(value, EncodingError.Context(codingPath: codingPath + keys, debugDescription: "Invalid JSON value"))
}
})
}
mutating func encodeJSONDictionary(_ value: Dictionary<String, Any>) throws {
var nestedContainer = self.nestedContainer(keyedBy: JSONCodingKeys.self)
try nestedContainer.encodeJSONDictionary(value)
}
}
Here's a code snippet for that 这是一个代码片段
However, this code snippet will fail in Swift 4.1 which should be released within the first half of 2018. 但是,此代码段将在Swift 4.1中失败,该版本应在2018年上半年发布。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.