From 99225f86fafffd749218c15b38fcc8cf2ee9c719 Mon Sep 17 00:00:00 2001 From: Marek Zvara Date: Fri, 4 Jun 2021 09:44:27 +0200 Subject: [PATCH 1/3] AnyEncodable support - wrapper for custom variables that conforms to Encodable --- AnyCodable/EncodingContainer+AnyCollection.swift | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/AnyCodable/EncodingContainer+AnyCollection.swift b/AnyCodable/EncodingContainer+AnyCollection.swift index b08f5bd..9d13fd6 100644 --- a/AnyCodable/EncodingContainer+AnyCollection.swift +++ b/AnyCodable/EncodingContainer+AnyCollection.swift @@ -81,6 +81,8 @@ private extension KeyedEncodingContainer where K == AnyCodingKey { try encode(dict, forKey: key) case let array as [Any]: try encode(array, forKey: key) + case let encodable as AnyEncodable: + try encode(encodable, forKey: key) default: debugPrint("⚠️ Unsuported type!", v) continue @@ -113,6 +115,8 @@ private extension UnkeyedEncodingContainer { case let array as [Any]: var values = nestedUnkeyedContainer() try values.encode(array) + case let encodable as AnyEncodable: + try encode(encodable) default: debugPrint("⚠️ Unsuported type!", v) } @@ -129,3 +133,15 @@ private extension UnkeyedEncodingContainer { try container.encode(value) } } + +public struct AnyEncodable: Encodable { + + private let _encode: (Encoder) throws -> Void + public init(_ wrapped: T) { + _encode = wrapped.encode + } + + public func encode(to encoder: Encoder) throws { + try _encode(encoder) + } +} From c3467a463390d0d0b8ea08cb605fa2bdece4061a Mon Sep 17 00:00:00 2001 From: Marek Zvara Date: Fri, 4 Jun 2021 10:01:30 +0200 Subject: [PATCH 2/3] Decoding - cast Any to Decodable object --- AnyCodable/DecodingContainer+AnyCollection.swift | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/AnyCodable/DecodingContainer+AnyCollection.swift b/AnyCodable/DecodingContainer+AnyCollection.swift index 129a938..fb570c3 100644 --- a/AnyCodable/DecodingContainer+AnyCollection.swift +++ b/AnyCodable/DecodingContainer+AnyCollection.swift @@ -56,6 +56,11 @@ extension KeyedDecodingContainer { let values = try nestedContainer(keyedBy: AnyCodingKey.self, forKey: key) return try values.decode(type) } + + public func decode(_ type: [String: Any].Type, forKey key: KeyedDecodingContainer.Key) throws -> [String: T] { + let values = try nestedContainer(keyedBy: AnyCodingKey.self, forKey: key) + return try values.decode(type) + } /// Decodes a value of the given type for the given key, if present. /// @@ -118,6 +123,16 @@ private extension KeyedDecodingContainer { } return dictionary } + + func decode(_ type: [String: Any].Type) throws -> [String: T] { + var dictionary: [String: T] = [:] + for key in allKeys { + if let object = try? decode(T.self, forKey: key) { + dictionary[key.stringValue] = object + } + } + return dictionary + } } private extension UnkeyedDecodingContainer { @@ -145,3 +160,4 @@ private extension UnkeyedDecodingContainer { return elements } } + From 689e909c3094daba609b4983de1d42875161b853 Mon Sep 17 00:00:00 2001 From: Marek Zvara Date: Fri, 4 Jun 2021 10:07:03 +0200 Subject: [PATCH 3/3] decodeIfPresent with generic type T: Decodable --- AnyCodable/DecodingContainer+AnyCollection.swift | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/AnyCodable/DecodingContainer+AnyCollection.swift b/AnyCodable/DecodingContainer+AnyCollection.swift index fb570c3..9c5280a 100644 --- a/AnyCodable/DecodingContainer+AnyCollection.swift +++ b/AnyCodable/DecodingContainer+AnyCollection.swift @@ -99,6 +99,12 @@ extension KeyedDecodingContainer { try decodeNil(forKey: key) == false else { return nil } return try decode(type, forKey: key) } + + public func decodeIfPresent(_ type: [String: Any].Type, forKey key: KeyedDecodingContainer.Key) throws -> [String: T]? { + guard contains(key), + try decodeNil(forKey: key) == false else { return nil } + return try decode(type, forKey: key) + } } private extension KeyedDecodingContainer {