Skip to content

ytyubox/SuperCodable

Repository files navigation

SuperCodable

From Foundation

struct AStudent: Codable {
    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        self.aID = try container.decode(String.self, forKey: .aID)
        self.aName = try container.decode(String.self, forKey: .aName)
        let gradeDecoded = try container.decode(Double.self, forKey: .aGrade)
        self.AGrede = Int(gradeDecoded)
    }

    enum CodingKeys: String, CodingKey {
        case aName = "name"
        case aGrade = "grade"
        case aID = "id"
    }

    var aID: String
    var aName: String
    var AGrede: Int

    func encode(to encoder: Encoder) throws {
        var container = encoder.container(keyedBy: CodingKeys.self)
        try container.encode(aID, forKey: .aID)
        try container.encode(Double(AGrede), forKey: .aGrade)
        try container.encode(aName, forKey: .aName)
    }
}

To SuperCodable

struct Student: SuperCodable {
    @Keyed
    var id: String
    
    @Keyed("name") 
    var aName: String
    
    @KeyedTransform("grade", doubleTransform)
    var AGrade: Int
}

let doubleTransform = SCTransformOf<Int, Double> {
    (double) -> Int in
    Int(double)
} toEncoder: { (int) -> Double in
    Double(int)
}

Even random backend type

struct AnyValueJSON: SuperCodable {
    @KeyedTransform(IDTransform)
    var id:Int
}

 let data =
    #"""
    [
        {
            "id": "0",
        },
        {
            "id": 1,
        },
        {
            "id": "abc",
        },
        {
            "id": true,
        },
    ]
    """#.data(using: .utf8)!
let sut = try! JSONDecoder().decode([AnyValueJSON].self, from: data)
XCTAssertEqual(sut.count, 4)
XCTAssertEqual(sut.map(\.id), [0, 1, 0, 1])

Can be found in Tests/SuperCodableTests/AnyValueDecode.swift

Feature

  • Working with Nested Foundation.Codable property

Known side effect

  • SuperDecoable must construct from nothing init()
  • @Keyed var id:Int will do O(n) calculation on underlaying wrapper _VARIABLE_NAME into key VARIABLE_NAME. Be ware of variable name takes too long

Known Disability

  • Every property in a SuperCodable should a DecodableKey / EncodableKey, otherwise the property(which should be Codable) will simply ignored during the Codable process.

Why:

Basically Mirror can't mutating the object value during the init(from decoder:) throws, since we create the object from self.init()

Other notes

  • Inspired by: https://medium.com/trueid-developers/combined-propertywrapper-with-codable-swift-368dc4aa2703

  • Try to merge @KeyedTransform into @Keyed, but it required @Keyed var id: String to be @Keyed() var id: String, with extra () 🧐

  • Swift should auto generate STRUCT.init(....) for you, but if you using @Keyed var id: String without default value, it will generate init(id: Keyed<String>), by giving default value @Keyed var id: String = "" should solve this problem.

Know Issues

  • @Keyed var id:String? will cause fatalError on force unwrapping Keyed.value?, you can using @OptionalKeyed to make it works.
  • OptionalKeyed may / may not a good name, I am thinking of make the easy to change, maybe KeyedOptional is EASY change? 🤔

About

Codable, but with Super power made custom Codable behavior easy.

Topics

Resources

Stars

Watchers

Forks

Packages

No packages published

Contributors 2

  •  
  •  

Languages

pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy