https://github.com/the-yuyut/supercodable
Codable, but with Super power made custom Codable behavior easy.
https://github.com/the-yuyut/supercodable
codable easy-to-use propertywrapper swift
Last synced: 23 days ago
JSON representation
Codable, but with Super power made custom Codable behavior easy.
- Host: GitHub
- URL: https://github.com/the-yuyut/supercodable
- Owner: the-yuyut
- Created: 2021-04-10T10:58:07.000Z (almost 5 years ago)
- Default Branch: main
- Last Pushed: 2021-09-14T11:07:19.000Z (over 4 years ago)
- Last Synced: 2026-01-22T18:40:34.181Z (about 2 months ago)
- Topics: codable, easy-to-use, propertywrapper, swift
- Language: Swift
- Homepage:
- Size: 46.9 KB
- Stars: 24
- Watchers: 1
- Forks: 4
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# SuperCodable
## From Foundation
```swift
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
```swift
struct Student: SuperCodable {
@Keyed
var id: String
@Keyed("name")
var aName: String
@KeyedTransform("grade", doubleTransform)
var AGrade: Int
}
let doubleTransform = SCTransformOf {
(double) -> Int in
Int(double)
} toEncoder: { (int) -> Double in
Double(int)
}
```
## Even random backend type
```swift
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](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)`, 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? 🤔