Type 'Any' does not conform to protocol 'Decodable'
d-date opened this issue · comments
In DictionaryDecoder
, we found some build errors, which are caused from the type 'Any' does not conform to protocol 'Decodable'
. Please check and fix these if you don't mind.
open func container<Key: CodingKey>(keyedBy type: Key.Type) throws -> KeyedDecodingContainer<Key> {
let container = try lastContainer(forType: [String: Any].self)
return KeyedDecodingContainer(KeyedContainer<Key>(decoder: self, codingPath: [], container: container)) // <- error: Type `Any` does not conform to protocol `Decodable`
}
open func unkeyedContainer() throws -> UnkeyedDecodingContainer {
let container = try lastContainer(forType: [Any].self) // <- error: Type `Any` does not conform to protocol `Decodable`
return UnkeyedContanier(decoder: self, container: container)
}
...
func nestedContainer<NestedKey>(keyedBy type: NestedKey.Type, forKey key: Key) throws -> KeyedDecodingContainer<NestedKey> where NestedKey : CodingKey {
decoder.codingPath.append(key)
defer { decoder.codingPath.removeLast() }
let value = try find(forKey: key)
let dictionary = try decoder.unbox(value, as: [String: Any].self) // <- error: Type `Any` does not conform to protocol `Decodable`
return KeyedDecodingContainer(KeyedContainer<NestedKey>(decoder: decoder, codingPath: [], container: dictionary))
}
func nestedUnkeyedContainer(forKey key: Key) throws -> UnkeyedDecodingContainer {
decoder.codingPath.append(key)
defer { decoder.codingPath.removeLast() }
let value = try find(forKey: key)
let array = try decoder.unbox(value, as: [Any].self) // <- error: Type `Any` does not conform to protocol `Decodable`
return UnkeyedContanier(decoder: decoder, container: array)
}
So the workaround is to make Any into AnyDecodable so it ends up something like this:
public struct AnyDecodable : Decodable {
let value :Any
public init<T>(_ value :T?) {
self.value = value ?? ()
}
public init(from decoder :Decoder) throws {
let container = try decoder.singleValueContainer()
if let string = try? container.decode(String.self) {
self.init(string)
} else if let int = try? container.decode(Int.self) {
self.init(int)
} else {
self.init(())
}
// handle all the different types including bool, array, dictionary, double etc
}
}
I got that code from this post: https://medium.com/@azamsharp/understanding-type-erasure-in-swift-2bf8fc530653 where they talk about this issue.