Skip to content

Instantly share code, notes, and snippets.

@IanKeen
Last active August 8, 2023 22:02
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save IanKeen/f8ab1c9d53fbdf90a52ded7057acbb7f to your computer and use it in GitHub Desktop.
Save IanKeen/f8ab1c9d53fbdf90a52ded7057acbb7f to your computer and use it in GitHub Desktop.
AnyCodable
public struct AnyCodable: Codable {
public var base: Any
public init(_ base: Any) {
self.base = base
}
public init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
guard !container.decodeNil() else {
throw DecodingError.valueNotFound(Any.self, .init(codingPath: decoder.codingPath, debugDescription: "Found nil"))
}
func decode<T: Decodable>(_: T.Type) -> (Decoder) -> Any? {
return { try? T.init(from: $0) }
}
let types: [(Decoder) -> Any?] = [
decode(String.self),
decode(Bool.self),
decode(Int.self),
decode(Int8.self),
decode(Int16.self),
decode(Int64.self),
decode(UInt.self),
decode(UInt8.self),
decode(UInt16.self),
decode(UInt64.self),
decode(Double.self),
decode(Float.self),
decode([AnyCodable].self),
decode([String: AnyCodable].self)
]
for type in types {
if let value = type(decoder) {
self.base = value
return
}
}
throw DecodingError.typeMismatch(Any.self, .init(codingPath: decoder.codingPath, debugDescription: "Value isn't Decodable"))
}
public func encode(to encoder: Encoder) throws {
if base is NSNull {
return
}
guard let value = base as? Encodable else {
throw EncodingError.invalidValue(base, .init(codingPath: encoder.codingPath, debugDescription: "Value isn't Encodable"))
}
try value.encode(to: encoder)
}
}
extension KeyedDecodingContainer {
public func decode(_ type: [String: Any].Type, forKey key: K) throws -> [String: Any] {
return try decode([String: AnyCodable].self, forKey: key).mapValues(\.base)
}
}
extension KeyedEncodingContainer {
public mutating func encode(_ value: [String: Any], forKey key: K) throws {
try encode(value.mapValues(AnyCodable.init), forKey: key)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment