Skip to content

gcharita/CodableProperty

Repository files navigation

CodableProperty

CI Status Version License Platform Swift Package Manager compatible

CodableProperty is a framework written in Swift that works along with the build in Codable protocol. Uses the new propertyWrapper feature of Swift 5.1 to make type transformation easier.

Example

To run the example project, clone the repo, and run pod install from the Example directory first.

Requirements

  • iOS 8.0+ / macOS 10.9+ / tvOS 9.0+ / watchOS 2.0+
  • Xcode 11+
  • Swift 5.1+

How to use

To use CodableProperty just implement CodableTransformer protocol and use it inside your Codable model like this:

@CodableProperty<CustomCodableTransformer> var someProperty: SomeType

For example if you have the following JSON:

{
    "currency": "PLN",
    "rates": {
        "USD": 3.76,
        "EUR": 4.24,
        "SEK": 0.41
    }
}

And you want to map it in a model like this:

struct CurrencyConversion {
    var currency: String
    var rates: [ExchangeRate]
}

struct ExchangeRate {
    let currency: String
    let rate: Double
}

You can transform the JSON type to your model type by implementing CodableTransformer protocol:

struct RatesTransformer: CodableTransformer {
    typealias Value = [ExchangeRate]

    func value(from decoder: Decoder) throws -> Value {
        let container = try decoder.singleValueContainer()
        let dictionary = try container.decode([String: Double].self)

        return dictionary.map { key, value in
            ExchangeRate(currency: key, rate: value)
        }
    }

    func encode(value: Value, to encoder: Encoder) throws {
        var container = encoder.singleValueContainer()
        let dictionary = value.reduce(into: [String: Double]()) { result, exchangeRate in
            result[exchangeRate.currency] = exchangeRate.rate
        }
        try container.encode(dictionary)
    }
}

And use it in your Codable model like this:

struct CurrencyConversion: Codable {
    var currency: String
    @CodableProperty<RatesTransformer> var rates: [ExchangeRate]
}

struct ExchangeRate {
    let currency: String
    let rate: Double
}

If you model implements Decodable protocol instead of Codable you can specialize the type transformation only in decoding process by implementing DecodableTransformer protocol:

struct RatesTransformer: DecodableTransformer {
    typealias Value = [ExchangeRate]

    func value(from decoder: Decoder) throws -> Value {
        let container = try decoder.singleValueContainer()
        let dictionary = try container.decode([String: Double].self)

        return dictionary.map { key, value in
            ExchangeRate(currency: key, rate: value)
        }
    }
}

And use it like this:

struct CurrencyConversion: Decodable {
    var currency: String
    @DecodableProperty<RatesTransformer> var rates: [ExchangeRate]
}

The same applies also to Encodable models:

struct RatesTransformer: EncodableTransformer {
    typealias Value = [ExchangeRate]

    func encode(value: Value, to encoder: Encoder) throws {
        var container = encoder.singleValueContainer()
        let dictionary = value.reduce(into: [String: Double]()) { result, exchangeRate in
            result[exchangeRate.currency] = exchangeRate.rate
        }
        try container.encode(dictionary)
    }
}

struct CurrencyConversion: Encodable {
    var currency: String
    @EncodableProperty<RatesTransformer> var rates: [ExchangeRate]
}

Communication

  • If you found a bug, open an issue.
  • If you have a feature request, open an issue.

Installation

CocoaPods

CodableProperty is available through CocoaPods. To install it, simply add the following line to your Podfile:

pod 'CodableProperty'

Swift Package Manager

To add CodableProperty to a Swift Package Manager based project, add the following:

.package(url: "https://github.com/gcharita/CodableProperty.git", from: "1.0.0")

to the dependencies value of your Package.swift.

Special thanks

Special thanks to John Sundell. His example in this article inspired me to write this project.

License

CodableProperty is available under the MIT license. See the LICENSE file for more info.