# \[Pre-Pitch\] Codable Customization using PropertyWrappers

**URL:** <https://forums.swift.org/t/pre-pitch-codable-customization-using-propertywrappers/30244>\
**Category:** Pitches\
**Created:** [October 28, 2019, 2:31pm UTC](https://forums.swift.org/t/pre-pitch-codable-customization-using-propertywrappers/30244 "2019-10-28T14:31:49Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![GetSwifty](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/getswifty/32/39108_2.png) [@GetSwifty](https://forums.swift.org/u/GetSwifty)\
**Post date:** [October 28, 2019, 2:31pm UTC](https://forums.swift.org/t/pre-pitch-codable-customization-using-propertywrappers/30244/1 "2019-10-28T14:31:49Z")

</div>

I recently released v1.0 of [CodableWrappers](https://github.com/GottaGetSwifty/CodableWrappers) (posted [here](https://forums.swift.org/t/announcing-codablewrappers/30242)) if you would like to discuss the library). It's features seem possibly worth writing my first Pitch, so I'd like to gauge the interest level in a more fleshed out pitch and if so, discuss how it would work in Swift (or probably the standard library).

## Motivation

Currently the only method of adding custom Encoding/Decoding for [Codable](https://developer.apple.com/documentation/swift/codable) Types (without a custom implementation) is by adding options to the Encoder/Decoder. Although this is relatively fleshed out in `JSON(En/De)Coder`, there are still some major pain points.

1. Options must be set for every (En/De)coder used
2. The option Types are separate so e.g. [dateEncodingStrategy](https://developer.apple.com/documentation/foundation/jsonencoder/2895363-dateencodingstrategy) and [dateDecodingStrategy](https://developer.apple.com/documentation/foundation/jsondecoder/2895216-datedecodingstrategy) have separate implementations and are both required to handle full serialization.
3. The options aren't Portable and each (en/de)coder must supply their own options. Not even Swift's own [PropertyList(En/De)coder](https://developer.apple.com/documentation/foundation/propertylistencoder) has support for the same options as it's JSON cousin.
4. It's all or nothing. e.g. If a Type or it's children need to use more than a single `dateEncodingStrategy` they must manage it themselves.

## Proposed solution

Add a set of [Property Wrappers](https://github.com/apple/swift-evolution/blob/master/proposals/0258-property-wrappers.md) that customize the `Codable` implementation at the property level.

### Examples

```swift
struct MyDataType: Codable {
    @Base64Coding
    var myData: Data // Now encodes to a Base64 String
}

struct MyDateType: Codable {
    @SecondsSince1970DateCoding
    var myDate: Date // Now encodes to SecondsSince1970
}

```

Customization that requires additional info can be passed with a Generic Type adopting a protocol with the necessary requirements.

```swift
struct MyNonConformingValueProvider: NonConformingDecimalValueProvider {
    static var positiveInfinity: String = "100"
    static var negativeInfinity: String = "-100"
    static var nan: String = "-1"
}

struct MyFloatType: Codable {
    @NonConformingFloatCoding<MyNonConformingValueProvider>
    var myFloat: Float // Now encodes with the MyNonConformingValueProvider values for infinity/NaN
}

```

## Detailed design

The relevant source for the library is [here](https://github.com/GottaGetSwifty/CodableWrappers/tree/master/Sources/CodableWrappers) and a more technical writeup [here](https://www.getswifty.blog/blog/design-footnotes-for-codablewrappers). The current design uses a combination of protocols and generic @propertyWrappers to enable concise Property Wrappers and easy extension by adhering to a single protocol. This is then combined with a set of `typealias`es to define the specific desired Wrappers

Here's a simplified version of the protocols/wrapper:

```swift
public protocol StaticCoder: Codable {
    associatedtype CodingType: Encodable
    /// Mirror of `Encodable`'s `encode(to: Encoder)` but in a static context
    static func encode(value: CodingType, to encoder: Encoder) throws
    /// Mirror of `Decodable`'s `init(from: Decoder)` but in a static context
    static func decode(from decoder: Decoder) throws -> CodingType
}

public protocol StaticCodingWrapper: Codable {
    associatedtype CustomCoder: StaticCoder
}

extension StaticCodingWrapper {
    public init(from decoder: Decoder) throws {
        self.init(wrappedValue: try CustomCoder.decode(from: decoder))
    }

    public func encode(to encoder: Encoder) throws {
        try CustomCoder.encode(value: wrappedValue, to: encoder)
    }
}

@propertyWrapper
public struct CodingUses<CustomCoder: StaticCoder>: StaticCodingWrapper {

    public let wrappedValue: CustomCoder.CodingType
    public init(wrappedValue: CustomCoder.CodingType) {
        self.wrappedValue = wrappedValue
    }
}

```

So for base64 `Data`...

```swift
public struct Base64DataStaticCoder: StaticCoder {

    public static func decode(from decoder: Decoder) throws -> Data {
        let stringValue = try String(from: decoder)

        guard let value = Data.init(base64Encoded: stringValue) else {
            //throw an error
        }
        return value
    }

    public static func encode(value: Data, to encoder: Encoder) throws {
        try value.base64EncodedString().encode(to: encoder)
    }
}

// Full set of Property Wrappers

typealias Base64Encoding = EncodingUses<Base64DataStaticCoder>
typealias Base64Decoding = DecodingUses<Base64DataStaticCoder>
typealias Base64Coding = CodingUses<Base64DataStaticCoder>

typealias Base64EncodingMutable = EncodingUsesMutable<Base64DataStaticCoder>
typealias Base64DecodingMutable = DecodingUsesMutable<Base64DataStaticCoder>
typealias Base64CodingMutable = CodingUsesMutable<Base64DataStaticCoder>

```

This results in several advantages over what's currently available:

- It's Declarative. Serialization details can be constrained to the property definition rather than split between (en/de)coders and documentation
- Extendable. Adding a custom encoding option is as simple as implementing `StaticCoder`
- Single declaration. The customization happens at the property level so it applies to _all_ Encoders and Decoders. 1st party or otherwise
- Enables multiple (de/en)coding strategies within a single data structure without customizing the Codable implementation

## Integration

Although this _could_ replace the current options in `JSON(En/De)coder`, these approaches can coexist without any issues. If desired the relevant APIs could be deprecated in favor of this approach or if the current API is still desired their implementation could also be re-routed to use the `StaticCoder`s added by the new approach.

## Possible Roadblocks

### Property Wrapper Ergonomics

Since a Property Wrapper decides the mutability of it's wrapped Property, separate mutable versions of each property are required to support all use cases. e.g. `Base64Coding` and `Base64CodingMutable`. I can see this being improved at some point but I haven't seen any indication if/when that would be taking place.

### Possible API Confusion

The naming around this is...tricky. I can see potential confusion between the new APIs and the current `Codable` APIs. If this were to be added to the language some iteration on naming will likely be necessary.

## Alternatives Considered

If it's preferable not to expose all the Protocols/Types currently included as public, each Property Wrapper could be a full implementation with the encoding/decoding done directly in the Wrapper (or just `StaticCodingWrapper` removed). It would be more implementation heavy but could be done via code generation. This would remove the "Extendable" advantage, but would retain the others.

## Future Directions

One ability I've been itching for is to customize a Property's CodingKey with Attribute syntax rather than having to override and maintain the entirety of `CodingKeys`.

```swift

struct MyType: Codable {
    @CodingKey("first-name")
    var firstName: String
}

```

As far as I can tell, this is not currently possible with a Property Wrapper (if someone knows otherwise, please let me know how!). The simplest implementation I can see would be a step in CodingKeys generation that uses the passed name instead of the default.

Anyway, thanks for reading. Any feedback is appreciated!

---

<div class="post-metadata">

**Author:** ![mattpolzin](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/mattpolzin/32/6041_2.png) [@mattpolzin](https://forums.swift.org/u/mattpolzin)\
**Post date:** [October 28, 2019, 4:05pm UTC](https://forums.swift.org/t/pre-pitch-codable-customization-using-propertywrappers/30244/2 "2019-10-28T16:05:43Z")

</div>

I'll have to reply to this pitch more broadly later because I like the idea and have done similar experimentation (although I cut my own experimentation short when I realized it was not yet possible to compose Property Wrappers in Swift 5.1).

> [@GetSwifty](#):
>
> As far as I can tell, [overriding keys] is not currently possible with a Property Wrapper (if someone knows otherwise, please let me know how!).

I think you would be able to do this by overloading both `decode<T>(_ type: T.Type, forKey key: Self.Key)` and `decodeIfPresent<T>(_ type: T.Type, forKey key: Self.Key)` to grab a string from your property wrapper and use it in a simple `CodingKey` type that just wrapped that string (or storing said `CodingKey`, already initialized, in the property wrapper).

---

<div class="post-metadata">

**Author:** ![GetSwifty](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/getswifty/32/39108_2.png) [@GetSwifty](https://forums.swift.org/u/GetSwifty)\
**Post date:** [October 28, 2019, 4:15pm UTC](https://forums.swift.org/t/pre-pitch-codable-customization-using-propertywrappers/30244/3 "2019-10-28T16:15:59Z")

</div>

> [@mattpolzin](#):
>
> grab a string from your property wrapper

That was the limit I couldn't get around without getting super hacky. `Decodable`'s `init(from decoder: Decoder)` means the passed `String` needs to be available statically. This _could_ be done by passing a Type similar to `NonConformingFloatCoding`, but IMO at that point it's not really any easier than overriding `CodingKeys`. Is there another way I haven't thought of?

---

<div class="post-metadata">

**Author:** ![mattpolzin](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/mattpolzin/32/6041_2.png) [@mattpolzin](https://forums.swift.org/u/mattpolzin)\
**Post date:** [October 28, 2019, 4:26pm UTC](https://forums.swift.org/t/pre-pitch-codable-customization-using-propertywrappers/30244/4 "2019-10-28T16:26:35Z")

</div>

Hmm, yeah, I just did 5 minutes of prototyping and I think the wall I hit was that the approach I was after does not allow one-off overrides. It works if you want to specify all of the coding keys via property wrappers, but that is much less compelling (it just amounts to decentralizing the `CodingKeys` `enum`).

---

<div class="post-metadata">

**Author:** ![anreitersimon](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/anreitersimon/32/7269_2.png) [@anreitersimon](https://forums.swift.org/u/anreitersimon)\
**Post date:** [October 28, 2019, 6:05pm UTC](https://forums.swift.org/t/pre-pitch-codable-customization-using-propertywrappers/30244/5 "2019-10-28T18:05:22Z")

</div>

Maybe another approach to making the arguments of a propertyWrapper available during encoding/decoding would be to modify the code generated by property wrappers and Codable.

And in addition let the propertyWrapper provide a "Builder" type that builds/decodes/encodes the propertyWrapper

Using the example of `CodingKey` (renamed to `CustomCodingKey` to avoid confusion with the `CodingKey` protocol)

```swift
@propertyWrapper
struct CustomCodingKey<Value: Codable> {
    var wrappedValue: Value
    var key: String

    struct PropertyBuilder {
        var key: String

        init(_ key: String) {
            self.key = key
        }
        private struct StringCodingKey: CodingKey {
            let stringValue: String
            let intValue: Int? = nil
        }

        func build() -> CustomCodingKey<Value> {
            return CustomCodingKey(wrappedValue: wrappedValue, key: key)
        }

        func decode<Key: CodingKey>(from decoder: Decoder, forKey key: Key) throws -> CustomCodingKey<Value> {
            let container = try decoder.container(keyedBy: StringCodingKey.self)
            let value = try container.decode(Value.self, forKey: StringCodingKey(stringValue: key))

            return CustomCodingKey(wrappedValue: value, key: key)
        }

    }
}

```

Given this example

```swift
struct MyType: Codable {
    @CustomCodingKey("first-name")
    var firstName: String
}

```

The generated code could be adapted to something like this

```swift
struct MyType: Codable {

    /// instead of trying to construct the propertyWrapper itself this would first attempt
    /// to construct the Builder and fallback to the current behaviour if it is not defined
    private static var _firstNameBuilder = CustomCodingKey<String>.PropertyBuilder("first-name")
    private var _firstName = _firstNameBuilder.build()

    var firstName: String {
        get { _firstName.wrappedValue }
        set { _firstName.wrappedValue = newValue }
    }

    init(from decoder: Decoder) throws {
        self._firstName = try _firstNameBuilder.decode(from: decoder, forKey: .firstName)
    }

}

```

---

<div class="post-metadata">

**Author:** ![GetSwifty](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/getswifty/32/39108_2.png) [@GetSwifty](https://forums.swift.org/u/GetSwifty)\
**Post date:** [October 28, 2019, 7:25pm UTC](https://forums.swift.org/t/pre-pitch-codable-customization-using-propertywrappers/30244/6 "2019-10-28T19:25:55Z")

</div>

I think something like that could work.

On that strain, I wonder if a simpler solution would be some sort of ‘staticPropertyWrapper’ that generates static properties/methods. My guess is it could use some sort of defined Builder pattern like you have, but my experience with that kind of feature is limited so I’m a bit out of my depth as far as implementation.

---

<div class="post-metadata">

**Author:** ![jawbroken](https://avatars.discourse-cdn.com/v4/letter/j/cc9497/32.png) [@jawbroken](https://forums.swift.org/u/jawbroken)\
**Post date:** [October 29, 2019, 1:59am UTC](https://forums.swift.org/t/pre-pitch-codable-customization-using-propertywrappers/30244/7 "2019-10-29T01:59:53Z")

</div>

> [@GetSwifty](#):
>
> Since a Property Wrapper decides the mutability of it's wrapped Property, separate mutable versions of each property are required to support all use cases. e.g. `Base64Coding` and `Base64CodingMutable`.

Immutability at the property level should be rare, so I'm not sure it's worth doubling the API surface and making the common case name longer to support it. If it's deemed necessary to have both, I would prefer to make `Base64Coding` be the mutable version and find a new set of names for the immutable ones.

---

<div class="post-metadata">

**Author:** ![GetSwifty](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/getswifty/32/39108_2.png) [@GetSwifty](https://forums.swift.org/u/GetSwifty)\
**Post date:** [October 29, 2019, 2:02am UTC](https://forums.swift.org/t/pre-pitch-codable-customization-using-propertywrappers/30244/8 "2019-10-29T02:02:23Z")

</div>

> [@jawbroken](#):
>
> Immutability at the property level should be rare

FWIW, almost all my `Codable` Types are composed entirely of `let` properties. Maybe your experience is different?

---

<div class="post-metadata">

**Author:** ![jawbroken](https://avatars.discourse-cdn.com/v4/letter/j/cc9497/32.png) [@jawbroken](https://forums.swift.org/u/jawbroken)\
**Post date:** [October 29, 2019, 2:10am UTC](https://forums.swift.org/t/pre-pitch-codable-customization-using-propertywrappers/30244/9 "2019-10-29T02:10:44Z")

</div>

For me, it's the logical combination of two observations about idiomatic Swift:

1. Most types should be value types.
2. Immutable properties of value types are very rarely useful. Making a new instance of the type with a property or properties changed is identical to just mutating properties directly.

You might disagree with one or the other, though.

---

<div class="post-metadata">

**Author:** ![GetSwifty](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/getswifty/32/39108_2.png) [@GetSwifty](https://forums.swift.org/u/GetSwifty)\
**Post date:** [October 29, 2019, 2:37am UTC](https://forums.swift.org/t/pre-pitch-codable-customization-using-propertywrappers/30244/10 "2019-10-29T02:37:08Z")

</div>

Specifically, for me it's an indication of "This Type is not intended as a workspace". Many of my Codable Types are for API calls and IMO those Types should be strict reflections of the API. Not allowing mutation discourages other uses.

To follow the rabbit trail...more broadly I've been moving towards an increasingly functional and stateless approach. Mutable properties are even considered by some to be an anti-pattern (I'm only partially onboard with that). This is not to say there aren't other perfectly valid approaches. Imperative, OOP, etc. design patters will always have their use cases. But my perception is the general trend in the industry is toward Transforming over Mutating, so that's how I approached the design 🙂

Regardless, the whole issue can be circumvented by allowing the user to decide rather than the author of the Property Wrapper. But that's probably a discussion for a different thread 😌

---

<div class="post-metadata">

**Author:** ![Nevin](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/nevin/32/617_2.png) [@Nevin](https://forums.swift.org/u/Nevin)\
**Post date:** [October 29, 2019, 3:04am UTC](https://forums.swift.org/t/pre-pitch-codable-customization-using-propertywrappers/30244/11 "2019-10-29T03:04:01Z")

</div>

That argument is not convincing to me.

If you are truly using a functional, non-mutating style, then you are almost certainly working with value types.

And if you are working with value types, then you just have to declare the instance itself as a `let` to get immutability.

Similarly, if you are chaining functional calls, in Swift the return value of a function is immutable anyway.

So if you want immutability when working with data _or_ function calls, you already have it just by virtue of using value types.

Consequently, the natural design is to declare all members of a `struct` as `var`. Doing so has no downside, and it has the upside of convenience in those situations where you do need to mutate.

I personally view the use of `let` properties in a `struct` as a code smell. Properties should always be `var`, and in cases where you need to preserve an invariant, then `private(set)` is sufficient.

---

<div class="post-metadata">

**Author:** ![GetSwifty](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/getswifty/32/39108_2.png) [@GetSwifty](https://forums.swift.org/u/GetSwifty)\
**Post date:** [October 29, 2019, 5:27am UTC](https://forums.swift.org/t/pre-pitch-codable-customization-using-propertywrappers/30244/12 "2019-10-29T05:27:44Z")

</div>

> [@Nevin](#):
>
> Consequently, the natural design is to declare all members of a `struct` as `var` . Doing so has no downside, and it has the upside of convenience in those situations where you do need to mutate.
> 
> I personally view the use of `let` properties in a `struct` as a code smell. Properties should always be `var` , and in cases where you need to preserve an invariant, then `private(set)` is sufficient.

First, a [Purely Function Language](https://en.wikipedia.org/wiki/Purely_functional_programming) doesn't even _have_ mutation. IMO that's overly idealistic, but it's an approach developed with valid reasons. In that context allowing mutation is not only a code smell, _it's not even possible!_ 🙂

Second, yes any Property within a struct could be a `var` without violating value semantics. But _mutability_ is also about _design_. Take this User Type:

```swift
/// Sent and Returned from http://www.mySite.com/api/v1/user
struct User: Codable {
    var fullName: String
    var firstName: String
    var lastName: String

    convenience init(firstName: String, lastName: String) {
        self.firstName = firstName
        self.lastName = lastName
        self.fullName = "\(firstName) \(lastName)"
    }
}

```

Leaving the members as `var` means mutating _any_ property breaks another. This could be handled the OOP way with custom setters, but the "fullName" is going to be a headache and you now have several more Unit Tests you have to write. Add in `middleName, `suffix`, etc. and your nice concise Type just turned into 100 lines.

Or...you could just make them `let` and it's good to go.

IME minimizing API surface area in an application is nearly always a good thing. Fewer things to test, fewer things that can go wrong, and less of a chance someone (especially myself) will use it in unintended ways and break things. Again _there are other valid ways to approach this_, but there are good reasons to make struct members immutable.

Anyway this definitely not what this maybe-a-pitch is about 😄. If there's a meaningful majority that prefers the Mutable version being the default that's fine by me. It's definitely not a molehill I'll die on.

---

<div class="post-metadata">

**Author:** ![Nevin](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/nevin/32/617_2.png) [@Nevin](https://forums.swift.org/u/Nevin)\
**Post date:** [October 29, 2019, 5:42am UTC](https://forums.swift.org/t/pre-pitch-codable-customization-using-propertywrappers/30244/13 "2019-10-29T05:42:50Z")

</div>

> [@GetSwifty](#):
>
> Take this User Type

If you intend `fullName` to be independent of the other two properties, then yes they should all be `var`. If you intend it instead to be derived from them, then it should use a computed property.

Regardless, [human names are difficult](https://www.kalzumeus.com/2010/06/17/falsehoods-programmers-believe-about-names/), so they would not be my go-to example for, well, anything except their own complexity.

> [@GetSwifty](#):
>
> a [Purely Function Language](https://en.wikipedia.org/wiki/Purely_functional_programming) doesn't even _have_ mutation

You are making my case for me. When doing functional things, no mutation is possible. Therefore, having member properties declared as `var` has no downside. They cannot and will not be mutated, so it does not matter how they are declared.

When doing other types of things, there is still no downside to declaring properties as `var`. If immutability is desired, then declare the instance itself as `let`.

However, if mutability is desired, then there _is_ a downside to having `let` properties, because that prevents mutation even though it is desired.

To recap, there is no downside to using `var` for member properties, regardless of programming paradigm. There _is_ a downside to using `let`.

---

<div class="post-metadata">

**Author:** ![GetSwifty](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/getswifty/32/39108_2.png) [@GetSwifty](https://forums.swift.org/u/GetSwifty)\
**Post date:** [October 29, 2019, 6:12am UTC](https://forums.swift.org/t/pre-pitch-codable-customization-using-propertywrappers/30244/14 "2019-10-29T06:12:33Z")

</div>

> [@Nevin](#):
>
> then it should use a computed property.

That doesn't work when it's coming from a 3rd party. (A server)

> [@Nevin](#):
>
> They cannot and will not be mutated, so it does not matter how they are declared.

As long as your property is a `var` it _can_ be mutated. An instance being `let` simply means you're _choosing_ not to mutate it and hoping future maintainers don't naively change it. If you're ok being at the mercy of [Murphy's Law](https://en.wikipedia.org/wiki/Murphy's_law) that's your choice. If the option's available there's someone who will do it. If you're not accounting for that, it's likely something will break.

1. The Imperative approach is to manage the state directly
2. The OOP approach is for the Type to manage it's State internally.
3. The Functional approach is to not _have_ a state.

Always having `var` uses #1, `private(set)` is using #2, but somehow #3 is accomplished at the same time? Seems 🐟y to me 😕

Anyway, seems like your mind's made up so agree to disagree. 🙂

---

<div class="post-metadata">

**Author:** ![Nevin](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/nevin/32/617_2.png) [@Nevin](https://forums.swift.org/u/Nevin)\
**Post date:** [October 29, 2019, 6:38am UTC](https://forums.swift.org/t/pre-pitch-codable-customization-using-propertywrappers/30244/15 "2019-10-29T06:38:00Z")

</div>

> [@GetSwifty](#):
>
> An instance being `let` simply means you're _choosing_ not to mutate it and hoping future maintainers don't naively change it.

It seems that you simultaneously have high expectations that `let` will (in the case of member properties) forever and always preserve immutability even in the face of future maintainers with different plans, while also having low expectations that `let` will not (in the case of instance declarations) do exactly the same thing.

You can’t have it both ways.

Either `let` is a strong guarantee of immutability, in which case using it at the instance level is sufficient and properties are free to be `var`; or else `let` is a weak guarantee and future maintainers can easily work around it by, for example, creating a new instance with different values and passing that along instead, in which case the properties might as well have been `var` all along.

Again, I repeat, when using value types, there is no upside to declaring properties as `let`, there is only downside.

• • •

Or, to use an example from a classic Swift video, there’s no sense in requiring people to build a whole new house just to change the temperature of their oven.

---

<div class="post-metadata">

**Author:** ![alextud](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/alextud/32/4377_2.png) [@alextud](https://forums.swift.org/u/alextud)\
**Post date:** [October 29, 2019, 11:37am UTC](https://forums.swift.org/t/pre-pitch-codable-customization-using-propertywrappers/30244/16 "2019-10-29T11:37:23Z")

</div>

Does property wrappers add cpu/memory overhead ?

Basically you just use property wrappers once (parse data from json). But every time you create / access that value, you need to pay the price for having 2 instances.

---

<div class="post-metadata">

**Author:** ![cukr](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/cukr/32/889_2.png) [@cukr](https://forums.swift.org/u/cukr)\
**Post date:** [October 29, 2019, 11:55am UTC](https://forums.swift.org/t/pre-pitch-codable-customization-using-propertywrappers/30244/17 "2019-10-29T11:55:03Z")

</div>

> [@alextud](#):
>
> Does property wrappers add cpu/memory overhead ?

> **[Compiler Explorer](https://godbolt.org/z/7tAsxt)**
>
> Compiler Explorer is an interactive online compiler which shows the assembly output of compiled C++, Rust, Go (and many more) code.

It seems it doesn't add memory overhead, and no CPU overhead for getter and setter. It does add some instructions for `modify`, but I don't know enough about assembly to say if that's significant.

---

<div class="post-metadata">

**Author:** ![karim](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/karim/32/1412_2.png) [@karim](https://forums.swift.org/u/karim)\
**Post date:** [October 29, 2019, 1:49pm UTC](https://forums.swift.org/t/pre-pitch-codable-customization-using-propertywrappers/30244/18 "2019-10-29T13:49:29Z")

</div>

I wonder if the mutability concern could be resolved by having it as an input into the property wrapper init?

`@Base64Coding`  
vs  
`@Base64Coding(immutable: true)`

In any case, I'm with @Nevin on this debate. Mutable would need to be the assumed default.

But as much as I want to like this pitch, I think the one killer feature here is the `@CodingKey()` wrapper, and If that can't be solved, it's going to be a glaring omission. I can't count the number of times I've been forced to declare an entire CodingKeys enum retyping every property in a type, in order to override the key for a single property 😑

I think the real problem I have with this overall is that it seems like Custom Attributes (annotations) is the right tool here, not actually Property Wrappers. I may be wrong, but seems to me that if custom attributes was part of the language before Codable was created, then they would have played a role in the creation of that feature.

But because the en/decoding synthesis wasn't written against a system of custom attributes, we're trying to shoe-horn in a solution based on Property Wrappers, and that force-fit is the root cause of a lot of the issues you're encountering (ie: mutable vs. immutable, difficulty w/ coding key synthesis, etc).

I'd personally prefer to see a more ambitious pitch that takes this to the deeper level of enhancing the actual codable synthesis to use a system of compile-time annotations built on custom attributes.

---

<div class="post-metadata">

**Author:** ![GetSwifty](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/getswifty/32/39108_2.png) [@GetSwifty](https://forums.swift.org/u/GetSwifty)\
**Post date:** [October 29, 2019, 2:08pm UTC](https://forums.swift.org/t/pre-pitch-codable-customization-using-propertywrappers/30244/19 "2019-10-29T14:08:31Z")

</div>

> [@karim](#):
>
> I wonder if the mutability concern could be resolved by having it as an input into the property wrapper init?

I think that would require a magic variable/parameter, which I think can be avoided by changing the rules to:

- (The current rule) A PropertyWrapper may disallow `set`
- If the wrapped Property is set `let`, the `set` is not generated and `wrappedValue.set` is set to private.

> [@karim](#):
>
> I think the one killer feature here is the `@CodingKey()` wrapper

I would really like to see this, but I think it requires new features being added to the language. As it is I'm hoping this could simply be added to the standard library. It solves real problems I deal with regularly and when the necessary language features are available, `@CodingKey` can be added.

---

<div class="post-metadata">

**Author:** ![GetSwifty](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/getswifty/32/39108_2.png) [@GetSwifty](https://forums.swift.org/u/GetSwifty)\
**Post date:** [October 29, 2019, 2:13pm UTC](https://forums.swift.org/t/pre-pitch-codable-customization-using-propertywrappers/30244/20 "2019-10-29T14:13:10Z")

</div>

> [@Nevin](#):
>
> You can’t have it both ways.

There are major differences between `let` for an instance vs `let` for a property. But again, that's not what this thread is about, so agree to disagree. PM me if you want to keep debating 🙂

[Next page](https://forums.swift.org/t/pre-pitch-codable-customization-using-propertywrappers/30244.md?page=2)
