Last active
August 19, 2021 14:43
-
-
Save EricRabil/b03ff3abbc1a745fa9e809bc1878f609 to your computer and use it in GitHub Desktop.
Write anonymous encoding and decoding functions that can convert any arbitrary values back and forth
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import Foundation | |
| // somewhere in a different module | |
| struct MyArbitraryUncodableStruct { | |
| let aBool: Bool | |
| let aInt: Int | |
| } | |
| extension JSONEncoder { | |
| private class CustomEncodable: Encodable { | |
| private let encode: (Encoder) throws -> () | |
| init(_ encode: @escaping (Encoder) throws -> ()) { | |
| self.encode = encode | |
| } | |
| func encode(to encoder: Encoder) throws { | |
| try encode(encoder) | |
| } | |
| } | |
| func encode(_ cb: @escaping (Encoder) throws -> ()) throws -> Data { | |
| try encode(CustomEncodable(cb)) | |
| } | |
| } | |
| extension JSONDecoder { | |
| private class CustomDecodable: Decodable { | |
| static var decoder: ((Decoder) throws -> Any)! | |
| let decodedValue: Any | |
| required init(from decoder: Decoder) throws { | |
| decodedValue = try Self.decoder(decoder) | |
| } | |
| } | |
| func decode<P>(data: Data, _ cb: @escaping (Decoder) throws -> P) throws -> P { | |
| // this would be better but we cant have anonymous classes yet so fuck you and also JSONParser is marked internal so fuck you | |
| // https://github.com/apple/swift-corelibs-foundation/blob/main/Sources/Foundation/JSONSerialization%2BParser.swift | |
| CustomDecodable.decoder = cb | |
| defer { CustomDecodable.decoder = nil } | |
| return try decode(CustomDecodable.self, from: data).decodedValue as! P | |
| } | |
| } | |
| // your code | |
| let instance = MyArbitraryUncodableStruct(aBool: true, aInt: 54) | |
| extension MyArbitraryUncodableStruct { | |
| enum CodingKeys: CodingKey { | |
| case aBool, aInt | |
| } | |
| } | |
| let data = try JSONEncoder().encode { encoder in | |
| var container = encoder.container(keyedBy: MyArbitraryUncodableStruct.CodingKeys.self) | |
| try container.encode(instance.aBool, forKey: .aBool) | |
| try container.encode(instance.aInt, forKey: .aInt) | |
| } | |
| let parsed = try JSONDecoder().decode(data: data) { decoder -> MyArbitraryUncodableStruct in | |
| let container = try decoder.container(keyedBy: MyArbitraryUncodableStruct.CodingKeys.self) | |
| return MyArbitraryUncodableStruct( | |
| aBool: try container.decode(Bool.self, forKey: .aBool), | |
| aInt: try container.decode(Int.self, forKey: .aInt) | |
| ) | |
| } | |
| print(data) | |
| print(String(decoding: data, as: UTF8.self)) | |
| print(parsed.aBool) | |
| print(parsed.aInt) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment