CodableKit is a Swift macro package designed to simplify the use of Swift's Codable
protocol by allowing easy
integration of default values, reducing the amount of auxiliary code you need to write.
- Custom coding keys
- Default values for missing data
- Handling of decoding failures
- String to struct transcoding
- Property ignoring
- Explicit nil handling
- Custom key property generation
To use the Codable macro, simply add the @Codable
attribute to your struct declaration.
@Codable
struct Car {
let brand: String
let model: String
var year: Int = 2024
}
By setting the default value of the year
property to 2024, the value will be 2024 when the raw data does not include that property.
The Codable macro provides several additional features through the @CodableKey
attribute and its associated options:
- Custom Coding Keys: Change the coding key for a property.
@CodableKey("uid")
let id: UUID
- CodableKeyOptions: Customize the behavior of properties using various options.
@CodableKey(options: [.useDefaultOnFailure, .transcodeRawString])
var someProperty: SomeType
You can find the details in the CodableKeyOptions.swift file.
Available options:
-
.default
: The default options (empty set). -
.ignored
: The property will be ignored during encoding and decoding. -
.explicitNil
: The key will be explicitly set tonil
(null
) when encoding and decoding, instead of being omitted. -
.generateCustomKey
: Generates a computed property to access the key when a custom CodableKey is used. -
.transcodeRawString
: Transcodes the value between raw string and the target type during encoding and decoding. -
.useDefaultOnFailure
: Uses the default value (if set) when decoding or encoding fails.
Here's a comprehensive example showcasing various features:
@Codable
struct User {
@Codable
struct Car {
let brand: String
let model: String
let year: Int
}
@CodableKey("uid")
let id: UUID
let name: String
var age: Int = 24
@CodableKey(options: .useDefaultOnFailure)
var avatar: URL? = nil
@CodableKey(options: .transcodeRawString)
var car: Car
@CodableKey(options: .ignored)
let thisPropertyWillNotBeIncluded: String = "ignored"
@CodableKey("custom_email", options: .generateCustomKey)
var email: String
@CodableKey(options: .explicitNil)
var optionalField: String?
}
In this example:
-
id
uses a custom coding key "uid". -
age
has a default value of 24. -
avatar
uses the default value if decoding fails. -
car
is transcoded from a raw string to theCar
struct. -
thisPropertyWillNotBeIncluded
is ignored during encoding and decoding. -
email
uses a custom key "custom_email" and generates a computed property for access. -
optionalField
will be explicitly set tonull
whennil
, instead of being omitted.
.package(url: "https://github.com/WendellXY/CodableKit.git", from: "1.0.0"),
For those who still use Swift 5 or have dependencies that require Swift 5 or swift-syntax 510.0.0, you can use the previous 0.x version of CodableKit, which is compatible with Swift 5 and should cover most of features in the latest version. Be aware that the 0.x version will not be developed anymore, and it is recommended to upgrade to the latest version.
.package(url: "https://github.com/WendellXY/CodableKit.git", from: "0.4.0"),
When applying this macro to a base class, in the class definition header, you should not add any inheritance to the class. Otherwise, this class will be considered as a class with a superclass, because the macro cannot identify whether the inheritance is a class or a protocol during macro expansion.
// Codable will consider the BaseUser as a base class since it does not have any inheritance
@Codable
class BaseUser { }
// Codable will consider the HashableUser as a subclass even if the inheritance just contains a protocol
@Codable
class HashableUser: Hashable { }
// So you have to write the HashableUser like:
@Codable
class HashableUser { }
extension HashableUser: Hashable { }
Please feel free to contribute to CodableKit
! Any input and suggestions are always appreciated.