Skip to content

Instantly share code, notes, and snippets.

@AliSoftware
Created October 16, 2019 13:38
Show Gist options
  • Select an option

  • Save AliSoftware/eff27d01bf0b4b74c0239001fd0c4f50 to your computer and use it in GitHub Desktop.

Select an option

Save AliSoftware/eff27d01bf0b4b74c0239001fd0c4f50 to your computer and use it in GitHub Desktop.

Revisions

  1. AliSoftware renamed this gist Oct 16, 2019. 1 changed file with 0 additions and 0 deletions.
  2. AliSoftware created this gist Oct 16, 2019.
    32 changes: 32 additions & 0 deletions Example.swift
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,32 @@
    // Declare a custom transform

    enum IntAsPoundString: TransformerType {
    static let encodeTransform = { (base: Int) throws -> String in "#\(base)#" }
    static let decodeTransform = { (encoded: String) throws -> Int in Int(encoded.replacingOccurrences(of: "#", with: "")) ?? 0 }
    }

    struct Article: Codable {
    @CustomCodable<IntAsPoundString>
    var id: Int
    var name: String
    }



    // Demo

    let art1 = Article(id: 42, name: "H2G2")
    let encoder = JSONEncoder()
    encoder.outputFormatting = .prettyPrinted
    let j1 = String(data: try encoder.encode(art1), encoding: .utf8) ?? "<nil>"
    print(j1)
    /*
    {
    "id" : "#42#",
    "name" : "H2G2"
    }
    */

    let art1decoded = try JSONDecoder().decode(Article.self, from: j1.data(using: .utf8)!)
    print(art1decoded.id, art1decoded.name)
    /* 42 H2G2 */
    25 changes: 25 additions & 0 deletions PropertyWrapper+CustomCodable.swift
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,25 @@
    import Foundation

    protocol TransformerType {
    associatedtype BaseType
    associatedtype TypeForCoding: Codable
    static var encodeTransform: (BaseType) throws -> TypeForCoding { get }
    static var decodeTransform: (TypeForCoding) throws -> BaseType { get }
    }

    @propertyWrapper
    struct CustomCodable<Transformer: TransformerType> {
    var wrappedValue: Transformer.BaseType
    }
    extension CustomCodable: Codable {
    init(from decoder: Decoder) throws {
    let container = try decoder.singleValueContainer()
    let encoded = try container.decode(Transformer.TypeForCoding.self)
    self.wrappedValue = try Transformer.decodeTransform(encoded)
    }
    func encode(to encoder: Encoder) throws {
    var container = encoder.singleValueContainer()
    let encoded = try Transformer.encodeTransform(self.wrappedValue)
    try container.encode(encoded)
    }
    }