A Collection of PropertyWrappers to make custom Serialization of Swift Codable Types easy

Overview

CodableWrappers

Swift Package Manager Platforms Build Status

Simplified Serialization with Property Wrappers

Move your Codable and (En/De)coder customization to annotations!

struct YourType: Codable {
    @MillisecondsSince1970DateCoding
    var millisecondsDate: Date
    @Base64Coding
    var someData: Data
    @OmitCoding
    var temporaryProperty
}

2.0's released! Release Notes


Installation

Swift Package Manager *Preferred*

URL:

https://github.com/GottaGetSwifty/CodableWrappers.git

Manifest:

dependencies: [
    .package(url: "https://github.com/GottaGetSwifty/CodableWrappers.git", .upToNextMajor(from: "2.0.0" )),
]

CocoaPods

pod 'CodableWrappers', '~> 2.0.0'

Info

Available Property Wrappers

Other Customization

Additional Links


Advantages

  • Declarative
  • Extendable
  • Declare once for all Encoders and Decoders. (e.g. JSONEncoder and PropertyListEncoder)
  • Custom (de/en)coding without overriding encode(to: Encoder) or init(with decoder) for your whole Type
  • Varied (de/en)coding strategies allowed
  • Cross Platform

Compatibility

2.x has a Swift 5.2 as it's minimum. 5.1 is available on 1.x


@EncodeNulls

For a Property that should encode null for nil values

struct MyType: Codable {
    @EncodeNulls
    var myText: String? // Will not be omitted when nil, e.g. will encode to `null` in JSON and `$null` in PLISTs
}

Lossy Collections

@LossyArrayDecoding
@LossyDictionaryDecoding
@LossySetDecoding

Filters null values during decoding without throwing an Error

private struct LossyCollectionModel: Codable, Equatable {
    @LossyArrayDecoding
    var array: [String] // Ignores null values without throwing an Error
    @LossyDictionaryDecoding
    var dictionary: [String:String] // Ignores null values without throwing an Error
    @LossySetDecoding
    var set: Set<String> // Ignores null values without throwing an Error
}

Empty Defaults

When you want to encode/decode an empty value rather than decoding nil or omitting encoding

struct MyType: Codable {
    @FallbackEncoding<EmptyInt>
    var int: Int? // will encode `0` when nil
    @FallbackDecoding<EmptyString>
    var string: String // will decode to "" when value was missing/nil
    @FallbackCoding<EmptyArray>
    var array: [Int]? // will encode/decode to [] when missing/nil
}
All Empty Values
EmptyBool
EmptyString
EmptyInt
EmptyInt16
EmptyInt32
EmptyInt64
EmptyInt8
EmptyUInt
EmptyUInt16
EmptyUInt32
EmptyUInt64
EmptyUInt8
EmptyCGFloat
EmptyDouble
EmptyFloat
EmptyFloat16
EmptyArray
EmptyDictionary
EmptySet

Empty defaults are available for most typical Foundation Types

Other Fallbacks

Any other kind of default can be provided by a custom FallbackValueProvider

public struct DistantFutureDateProvider: FallbackValueProvider {
    public static var defaultValue: Date { Date.distantFuture }
}

struct MyType: Codable {
    @FallbackEncoding<DistantFutureDateProvider>
    var updatedDate: Date?
}

@OmitCoding

For a Property you want to be ignore when (en/de)coding

struct MyType: Codable {
    @OmitCoding
    var myText: String? // Never encodes and ignores a value if one is in decoded data.
}

@Base64Coding

For a Data property that should be serialized to a Base64 encoded String

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

@SecondsSince1970DateCoding

For a Date property that should be serialized to SecondsSince1970

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

@MillisecondsSince1970DateCoding

For a Date property that should be serialized to MillisecondsSince1970

struct MyType: Codable {
    @MillisecondsSince1970DateCoding
    var myDate: Date // Now encodes to MillisecondsSince1970
}

@DateFormatterCoding<DateFormatterStaticCoder>

For other Date formats create a Type that adheres to the DateFormatterStaticCoder Protocol and use the convenience @DateFormatterCoding typealias or @CodingUses<StaticCoder>.

struct MyCustomDateCoder: DateFormatterStaticCoder {
    static let dateFormatter: DateFormatter = {
        let formatter = DateFormatter()
        formatter.dateFormat = "MM:dd:yy H:mm:ss"
        return formatter
    }()
}

struct MyType: Codable {
    @DateFormatterCoding<MyCustomDateCoder>
    var myDate: Date // Now encodes to the format: "MM:dd:yy H:mm:ss"
}

@ISO8601DateCoding

For a Date property that should be serialized using the ISO8601DateFormatter

struct MyType: Codable {
    @ISO8601DateCoding
    var myDate: Date // Now encodes to ISO8601
}

@ISO8601DateFormatterCoding<ISO8601DateFormatterStaticCoder>

For other Date formats create a Type that adheres to the ISO8601DateFormatterStaticCoder Protocol and use the convenience @ISO8601DateFormatterCoding typealias or @CodingUses<StaticCoder>.

@available(macOS 10.12, iOS 10.0, watchOS 3.0, tvOS 10.0, *)
struct MyCustomISO8601DateFormatter: ISO8601DateFormatterStaticCoder {
    static let iso8601DateFormatter: ISO8601DateFormatter = {
        let formatter = ISO8601DateFormatter()
        formatter.formatOptions = [.withInternetDateTime, .withDashSeparatorInDate]
        return formatter
    }()
}


struct MyType: Codable {
    @ISO8601DateFormatterCoding<MyCustomISO8601DateFormatter>
    var myDate: Date // Now encodes with MyCustomISO8601DateFormatter's formatter
}

@NonConformingFloatCoding<ValueProvider>

When using a non-conforming Float, create a Type that adheres to NonConformingDecimalValueProvider and use @NonConformingFloatCoding<NonConformingDecimalValueProvider>

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

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

@NonConformingDoubleCoding<ValueProvider>

When using a non-conforming Double, create a Type that adheres to NonConformingDecimalValueProvider and use @NonConformingDoubleCoding<NonConformingDecimalValueProvider>

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

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

Bool Coding

Sometimes an API uses an Int or String for a booleans.

@BoolAsStringCoding

struct MyType: Codable {
    @BoolAsStringCoding
    var myBool: Bool // Now encodes/decodes as a String. `"true"` for `true` and `"false"` for `false`. (Values are lower-cased before decoding)
}

@BoolAsIntCoding

struct MyType: Codable {
    @BoolAsIntCoding
    var myBool: Bool // Now encodes/decodes as an Int. `1` for `true` and `0` for `false`.
}

Additional Customization

The architecture was built with extensibility in mind so Implementing your own custom coding is as simple as adhering to the StaticCoder protocol. You can then simply add @CodingUses<YourCustomCoder> to your property, or create a typealias to make it cleaner: typealias YourCustomCoding = CodingUses<YourCustomCoder>

In fact all the included Wrappers are built the same way!

Full Example

struct NanosecondsSince9170Coder: StaticCoder {

    static func decode(from decoder: Decoder) throws -> Date {
        let nanoSeconds = try Double(from: decoder)
        let seconds = nanoSeconds * 0.000000001
        return Date(secondsSince1970: seconds)
    }

    static func encode(value: Date, to encoder: Encoder) throws {
        let nanoSeconds = value.secondsSince1970 / 0.000000001
        return try nanoSeconds.encode(to: encoder)
    }
}

// Approach 1: CustomCoding
struct MyType: Codable {
    @CodingUses<NanosecondsSince9170Coder>
    var myData: Date // Now uses the NanosecondsSince9170Coder for serialization
}

// Approach 2: CustomEncoding Property Wrapper typealias

typealias NanosecondsSince9170Coding = CodingUses<NanosecondsSince9170Coder>

struct MyType: Codable {
    @NanosecondsSince9170Coding
    var myData: Date // Now uses the NanosecondsSince9170Coder for serialization
}

Take a look at these other examples to see what else is possible.


Property Mutability

In 2.0 all wrappers are Mutable by default and can be made Immutable via Property Wrapper Composition

struct MyType: Codable {
    @Immutable @SecondsSince1970DateCoding
    var createdAt: Date

    @SecondsSince1970DateCoding
    var updatedAt: Date

    mutating func update() {
        createdAt = Date() // ERROR - Cannot assign to property: 'createdAt' is a get-only property
        updatedAt = Date() // Works!
    }
}

Optionals

2.0 introduces @OptionalCoding<StaticCodingWrapper> to enable Optionals for a property.

struct MyType: Codable {
    @SecondsSince1970DateCoding
    var createdAt: Date

    @OptionalCoding<SecondsSince1970DateCoding>
    var updatedAt: Date?
}

Only Encoding or Decoding

Sometimes you are only able/wanting to implement Encoding or Decoding.

To enable this, (where practical/possible), all of the included Wrappers have Encoding and Decoding variants

Change Coder to Encoder/Decoder or Coding to Encoding/Decoding to implement only one E.g. @Base64Encoding, @SecondsSince1970DateDecoding, @EncodingUses<ACustomEncoder>, etc.

struct MyType: Encodable {
    @SecondsSince1970DateEncoding
    var myDate: Date
}

struct MyType: Decodable {
    @SecondsSince1970DateDecoding
    var myDate: Date
}

Contributions

If there is a standard Serialization strategy that could be added feel free to open an issue requesting it and/or submit a pull request with the new option.

Comments
  • Unable to compile with Xcode12.5 beta3

    Unable to compile with Xcode12.5 beta3

    Can't compile on macOS 11 (11.3 beta 20E5229a) using XCode 12.5 beta 3 (12E5244e) due to following error: 'Float16' is unavailable in macOS Not sure what the extent of this is or if it does build for other macOS versions? If not we can simply rewrite the swift version check as: #if swift(>=5.4) && !os(macOS)

    opened by JaapWijnen 12
  • Update CocoaPods version to 2.0.6

    Update CocoaPods version to 2.0.6

    The CocoaPods manager doesn't see the 2.0.6 fix because it is not specified in CodableWrappers.podspec

    You can test the difference specifying

    pod 'CodableWrappers', :git=>'https://github.com/aserdobintsev/CodableWrappers', :branch=>'fix/cocoapodsVersion'
    

    vs

    pod 'CodableWrappers',
    
    opened by aserdobintsev 4
  • `@Immutable @EncodeNulls` doesn’t work as expected

    `@Immutable @EncodeNulls` doesn’t work as expected

    Hey @GottaGetSwifty,

    Using @Immutable with @EncodeNulls doesn’t work as expected.

    struct TestModel: Encodable {
        @EncodeNulls var date1: Date?
        @Immutable @EncodeNulls var date2: Date?
    }
    
     print(String(data: try! JSONEncoder().encode(TestModel(date1: nil, date2: nil)), encoding: .utf8))
    
    // OUTPUT: "{\"date1\":null}"
    

    I also can’t seem to get this snippet to compile (related?):

    @Immutable @OptionalCoding<DateFormatterCoding<RFC3339DateCoder>> @EncodeNulls var myDate: Date?
    
    opened by Brett-Best 3
  • Fix: Float16 support

    Fix: Float16 support

    Apple responded to my feedback with:

    Float16 isn’t supported on Intel Macs, but should be available on Apple Silicon Macs.

    Introduced these warnings for the test cases:

    warning: conformance of 'Float16' to ‘Encodable' is only available in macOS 11.0 or newer warning: conformance of 'Float16' to ‘Decodable' is only available in macOS 11.0 or newer warning: conformance of 'Float16' to ‘Encodable' is only available in Mac Catalyst 14.0 or newer warning: conformance of 'Float16' to 'Decodable' is only available in Mac Catalyst 14.0 or newer

    Fixes https://github.com/GottaGetSwifty/CodableWrappers/issues/13.

    Note: you have write access to edit my branch.

    opened by Brett-Best 3
  • Added bypass for `AnyNullEncoder` when wrapped in `Immutable`

    Added bypass for `AnyNullEncoder` when wrapped in `Immutable`

    NullEncoding.swift includes a specific override of encode for AnyNullEncoder (NullEncoding.swift) to bypass the default behaviour of OptionalEncodingWrapper which would otherwise skip the property when the wrappedValue is nil.

    However, Immutable also overrides encoding of wrapped OptionalEncodingWrappers (ImmutableWrapper.swift) to check if the deeply nested wrappedValue is nil or not, which means the above AnyNullEncoder override is never called.

    This PR adds an additional bypass for AnyNullEncoders wrapped in AnyImmutableWrapper.

    opened by jayrhynas 2
  • Is it possible to decode to custom types?

    Is it possible to decode to custom types?

    Hi,

    I'm looking for a way to map/decode json values to custom Enums.

    For instance my API return status value which may be something like -1, 0 or 1 I also have an enum:

    enum Status: Int {
        case deleted = -1
        case inactive = 0
        case active = 1
    }
    

    Can I map these together? I tried implementing a custom mapper from your example buy it doest seem to accept custom types, such as Status. I want to be able to do something like this:

    return Status(rawValue: -1)

    and get my custom type

    opened by staticdreams 2
  • Decoding empty JSON string value into nil with Codable

    Decoding empty JSON string value into nil with Codable

    normal case:

    {
        "maintenance": true
    }
    
    {
        "maintenance": false
    }
    

    If there is no maintenance station then it will become empty string

    {
        "maintenance": ""
    }
    

    i want to have nil if maintenance is empty string in json

    struct Demo: Codable {
        var maintenance: Bool?
    }
    

    Is there a good way to do it?

    opened by WingCH 2
  • Using `@Immutable` with `@FallbackDecoding` doesn’t work as expected

    Using `@Immutable` with `@FallbackDecoding` doesn’t work as expected

    struct WorkingModel: Codable {
      @FallbackDecoding<EmptyDouble>
      var duration: Double = 0
    }
    
    struct FailingModel: Codable {
      @Immutable @FallbackDecoding<EmptyDouble>
      var duration: Double = 0
    }
    
    let json = "{}"
    let decoder = JSONDecoder()
    
    do {
      _ = try decoder.decode(WorkingModel.self, from: json.data(using: .utf8).unsafelyUnwrapped) // Works
      _ = try decoder.decode(FailingModel.self, from: json.data(using: .utf8).unsafelyUnwrapped) // Throws an error about missing key
    } catch {
      dump(error)
      fatalError()
    }
    

    Running the above code should produce an error about a missing key. Using breakpoints I was expecting ImmutableWrapper.swift:L41-L44 or ImmutableWrapper.swift:L64-L66 to be called. However, it didn’t appear that they were.

    opened by Brett-Best 2
  • Use default encoding with the optional wrapper

    Use default encoding with the optional wrapper

    Hi,

    What would be the simplest way to encode an optional as null if nil or use the default Codable encoding strategy if present ? I mean a generic way to do it on Codable to avoid writing static encoder for each of my Codable types.

    so : struct some: Encodable { @?? let thisShouldBeEncodedAsNull: String? = nil let thisShouldNotBeEncodedAsNull: String? = nil }

    would give in JSON: { "thisShouldBeEncodedAsNull": null }

    opened by AlexisQapa 2
  • print hi

    print hi

    Why does the code print "hi"?

    https://github.com/GottaGetSwifty/CodableWrappers/blob/develop/Sources/CodableWrappers/OptionalWrappers.swift#L44

    https://github.com/GottaGetSwifty/CodableWrappers/blob/develop/Sources/CodableWrappers/OptionalWrappers.swift#L98

    opened by nkavian 1
  • Updated travis-ci config to 🤞 catch broken builds sooner

    Updated travis-ci config to 🤞 catch broken builds sooner

    The package build/test fails on linux with different errors for swift 5.2 and 5.6. I did my best to follow the travis docs, but I couldn't test that part myself. Package.resolved seems like a lite version of a lock file, so I added it following the conventions of other package managers.

    opened by r3h0 1
  • `DateFormatterStaticDecoder` throws `valueNotFound` error instead of `dataCorrupted` error

    `DateFormatterStaticDecoder` throws `valueNotFound` error instead of `dataCorrupted` error

    https://github.com/GottaGetSwifty/CodableWrappers/blob/4eb46a4c656333e8514db8aad204445741de7d40/Sources/CodableWrappers/StaticCoders/DateCoding.swift#L60-L71 I was debugging an issue which was made a bit confusing because of throwing valueNotFound, would you like me to make a PR changing this to a dataCorrupted error?

    It would match the behaviour of:

    import Foundation
    
    let string = """
    { "date": "ehrtrthrt" }
    """
    
    struct Model: Codable {
      let date: Date
    }
    
    let decoder = JSONDecoder()
    decoder.dateDecodingStrategy = .iso8601
    
    do {
      let model = try decoder.decode(Model.self, from: Data(string.utf8))
    } catch {
      if case DecodingError.dataCorrupted = error {
        print("DecodingError is dataCorrupted")
      } else {
        // not called
      }
    }
    
    
    opened by Brett-Best 0
  • Default values when key is not present

    Default values when key is not present

    Hi, I've been working on a similar set of features as this project, until I found this one, great work!

    The one feature I'm missing is for a way to have a non optional field that contains a default value in case the key is not present in the input data. So far I was able to get to this solution, which works for my use case, and was wondering if it might be something that could be added to this project

    What I came up with was this:

    import Foundation
    
    public protocol DefaultValue<Value> where Value: Codable {
      associatedtype Value
    
      static var defaultValue: Value { get }
    }
    
    @propertyWrapper
    public struct DefaultCodable<D: DefaultValue>: Codable {
      private enum State<Value> {
        case uninitialized
        case initialized(Value)
      }
    
      private var innerValue: State<D.Value>
    
      public init(value: D.Value? = nil) {
        if let value {
          innerValue = .initialized(value)
        } else {
          innerValue = .uninitialized
        }
      }
    
      public var wrappedValue: D.Value {
        get {
          if case .initialized(let value) = innerValue {
            return value
          } else {
            return D.self.defaultValue
          }
        }
        set {
          innerValue = .initialized(newValue)
        }
      }
    
      fileprivate var isSet: Bool {
        if case .uninitialized = innerValue {
          return false
        } else {
          return true
        }
      }
    
      public func encode(to encoder: Encoder) throws {
        if case .initialized(let value) = innerValue {
          var container = encoder.singleValueContainer()
          try container.encode(value)
        }
      }
    
      public init(from decoder: Decoder) throws {
        let container = try decoder.singleValueContainer()
        self.innerValue = try .initialized(container.decode(D.Value.self))
      }
    }
    
    extension KeyedEncodingContainer {
      public mutating func encode<T>(
        _ value: DefaultCodable<T>,
        forKey key: KeyedEncodingContainer<K>.Key
      ) throws {
        if value.isSet {
          try encode(value.wrappedValue, forKey: key)
        }
      }
    }
    
    extension KeyedDecodingContainer {
      public func decode<T>(
        _ type: DefaultCodable<T>.Type,
        forKey key: Self.Key
      ) throws -> DefaultCodable<T> {
        if contains(key) {
          let value = try decode(T.Value.self, forKey: key)
          return DefaultCodable(value: value)
        } else {
          return DefaultCodable()
        }
      }
    }
    
    // Default Values
    
    public enum DefaultBoolTrue: DefaultValue {
      public static var defaultValue = true
    }
    
    public enum DefaultBoolFalse: DefaultValue {
      public static var defaultValue = false
    }
    

    which can be used like this:

    public enum DefaultNameUnknown: DefaultValue {
      public static var emptyDefault = "Unknown"
    }
    
    public struct UserInfo: Codable {
      @DefaultCodable<DefaultBoolFalse> public var admin: Bool
      @DefaultCodable<DefaultBoolTrue> public var isActive: Bool
    
      @DefaultCodable<DefaultNameUnknown> public var name: String
    
      public init() {}
    }
    

    And used like this:

    public enum DefaultNameUnknown: DefaultValue {
      public static var defaultValue = "Unknown"
    }
    
    public struct UserInfo: Codable {
      @DefaultCodable<DefaultBoolFalse> public var admin: Bool
      @DefaultCodable<DefaultBoolTrue> public var isActive: Bool
    
      @DefaultCodable<DefaultNameUnknown> public var name: String
    
      public init() {}
    }
    

    which results in

    let data = #"{}"#.data(using: .utf8)!
    
    let decoder = JSONDecoder()
    let user = try decoder.decode(UserInfo.self, from: data)
    print(user.admin) // false
    print(user.isActive) // true
    print(user.name) // Unknown
    

    This is using 5.7 syntax, but could probably be adapted. Also, there might be a better way to specify a default value other than types, but this worked for me well enough.

    Is this something that you might consider adding to CodableWrappers?

    opened by sergiocampama 4
  • Typo

    Typo

    https://github.com/GottaGetSwifty/CodableWrappers/blob/master/Sources/CodableWrappers/Core/OptionalWrappers.swift#L76

    I think this public struct OptionalEncoding<CustomDecoderWrapper: StaticEncoderWrapper>: OptionalEncodable { should be public struct OptionalEncoding<CustomEncoderWrapper: StaticEncoderWrapper>: OptionalEncodable {

    opened by nkavian 0
  • Can I combine OptionalCoding<BoolAsIntCoding> with FallbackEncoding<EmptyBool>?

    Can I combine OptionalCoding with FallbackEncoding?

    Hello, is it possible to combine the following two wrappers in some way?

    public struct EmptyBoolTrue: FallbackValueProvider {
        public static var defaultValue: Bool { true }
    }
    
    @OptionalCoding<BoolAsIntCoding>
    @FallbackEncoding<EmptyBoolTrue>
    var autoRenewWarning: Bool?
    

    The server sends 1 and 0 for booleans and I use Bool locally. What I would like to achieve is to set a default value of 1 or true whichever is possible if the key is missing or null but it seems the above two cannot be combined because one expects Int and the other Bool. How should I proceed regarding this, is there anything similar implemented that I can use as reference?

    opened by CochiorasBogdan 1
  • `@EncodeNulls` and `@OptionalEncoding<X>` can’t be used together

    `@EncodeNulls` and `@OptionalEncoding` can’t be used together

    I want to write something like this:

    @Immutable @EncodeNulls @OptionalEncoding<DateFormatterEncoding<RFC3339DateCoder>> var completedOn: Date?
    

    However, currently that doesn’t work. I did try a few variations but from what I could tell we don’t have the functionality to do this yet.

    @jayrhynas kindly helped me out and we were able to come up with:

    struct Model: Codable {
      @Immutable @EncodeOptionalNulls @OptionalEncoding<DateFormatterEncoding<RFC3339DateCoder>> var completedOn: Date?
    }
    
    /// Encodes an optional nil value in a singleValueContainer using `encodeNil` rather than it being omitted.
    typealias EncodeOptionalNulls<T: Encodable & OptionalEncodingWrapper> = EncodingUses<OptionalNullStaticEncoder<T>>
    
    struct OptionalNullStaticEncoder<T: Encodable>: StaticEncoder, AnyNullEncoder where T: OptionalEncodingWrapper {
      static func encode(value: T, to encoder: Encoder) throws {
        if case Optional<Any>.none = value.wrappedValue as Any {
          var container = encoder.singleValueContainer()
          try container.encodeNil()
          return
        }
        try value.encode(to: encoder)
      }
    }
    
    struct RFC3339DateCoder: DateFormatterStaticCoder {
      static let dateFormatter = with(DateFormatter()) {
        $0.timeZone = TimeZone(secondsFromGMT: 0)
        $0.locale = Locale(identifier: "en_US_POSIX")
        $0.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"
      }
    }
    

    I’m not sure if the above could be simplified or made so that an additional StaticEncoder struct is not needed?

    opened by Brett-Best 0
  • Implement CurrentPathCoding

    Implement CurrentPathCoding

    Hey! It is not final version of intended PR, but I wanted to make sure that author is interested in such feature. Implemented @CurrentPathCoding wrapper allows this JSON structure:

    {
        "title": "Cool title",
        "authorName": "John",
        "authorEmail": "[email protected]"
    }
    

    to be mapped to such model:

    struct Author: Codable {
        var authorName: String
        var authorEmail: String
    }
    
    struct Article: Codable {
        var title: String
        @CurrentPathCoding
        var author: Author
    }
    

    If you can approve that such wrapper has the right to life and you would merge it, I'll add documentation and tests and then finalise the PR.

    opened by ky1vstar 3
Releases(2.0.7)
  • 2.0.7(Feb 9, 2022)

    Minor bug fixe release

    What's Changed

    • Update CocoaPods version to 2.0.6 by @aserdobintsev in https://github.com/GottaGetSwifty/CodableWrappers/pull/17
    • Added bypass for AnyNullEncoder when wrapped in Immutable by @jayrhynas in https://github.com/GottaGetSwifty/CodableWrappers/pull/25

    New Contributors

    • @aserdobintsev made their first contribution in https://github.com/GottaGetSwifty/CodableWrappers/pull/17
    • @jayrhynas made their first contribution in https://github.com/GottaGetSwifty/CodableWrappers/pull/25

    Full Changelog: https://github.com/GottaGetSwifty/CodableWrappers/compare/2.0.6...2.0.7

    Source code(tar.gz)
    Source code(zip)
  • 2.0.6(May 18, 2021)

  • 2.0.5(May 17, 2021)

  • 2.0.4(May 4, 2021)

  • 2.0.3(May 4, 2021)

  • 2.0.2(Mar 11, 2021)

  • 2.0.1(Feb 23, 2021)

  • 2.0.0(Dec 30, 2020)

    Finally finished 2.0!

    Along with CocoaPod support, The major goal for this release is to reduce API surface level by unifying Property variation, make the abstractions more meaningful, and add a couple useful wrappers.

    Major (Sometimes) Breaking Changes

    Wrappers are now Mutable by default. @Immutable can be composed in front of a wrapper if a property is meant to be immutable. Types this replaces are marked as deprecated with renaming/fixits where possible. Wrappers can now be made Optional by including it in the Type @OptionalCoding. e.g. OptionalCoding. Types this replaces are marked as deprecated with renaming/fixits where possible.

    New wrappers:

    Source code(tar.gz)
    Source code(zip)
  • 1.2.1(Dec 21, 2020)

  • v1.2.0(Feb 8, 2020)

  • 1.1.0(Nov 18, 2019)

  • 1.0.0(Oct 28, 2019)

Owner
null
Easy-to-use segues in SwiftUI, allowing for presenting views using common UIKIt Segue types - push, modal and popover

Easy-to-use segues in SwiftUI, allowing for presenting views using common UIKIt Segue types - push, modal and popover

Gordan Glavaš 5 Apr 16, 2022
SafeDecoder - a swift package that set defaults when Codable fails to decode a field

SafeDecoder is a swift package that set defaults when Codable fails to decode a field. SafeDecoder supports configurable default values, See SafeDecoder.Configuration.

GodL 4 Mar 21, 2022
Powerful property wrapper to back codable properties.

BackedCodable Powerful property wrapper to back codable properties. Why Swift's Codable is a great language feature but easily becomes verbose and req

Jérôme Alves 472 Dec 18, 2022
An experimental functional programming language with dependent types, inspired by Swift and Idris.

Kara An experimental functional programming language with dependent types, inspired by Swift and Idris. Motivation Development of Kara is motivated by

null 40 Sep 17, 2022
Snapify is an opensource tweak to make the messages app behave like Snapchat's sending system

Snapify A simple tweak to remove the send button in messages, replaced by keyboard key What is Snapify? Snapify is an opensource tweak to make the mes

Hallie 4 Oct 29, 2021
Dicee-SwiftUI - This app show random dicee every time the you make click in button roll

Dicee-SwiftUI This app show random dicee every time the you make click in button

Adriancys Jesus Villegas Toro 0 Feb 4, 2022
SyntaxTree - This code attempts to make basic syntax trees in the Xcode console

SyntaxTree This code attempts to make basic syntax trees in the Xcode console. I

Yash 0 Feb 12, 2022
Example how to make, update and end Live Activity. With Dynamic Island and Lock Screen.

Live Activity Example Example how to make, update and end Live Activity. With Dynamic Island and Lock Screen. Full tutorial available at sparrowcode.i

Sparrow Code 9 Dec 8, 2022
A collection of Swift Tutorials built with Apple's DocC.

Swift Tutorials This is not a package, it's just a bunch of tutorials This project uses Apple's DocC (Documentation Compiler) to create a set of Swift

Swift Innovators Network 11 Aug 9, 2022
A patch collection to save your Xcode

Patch Xcode is worst IDE I have ever used Xcode 13.3 introduced a very annoying bug. When you type anything with Chinese IME in the LLDB console

Cyandev 101 Dec 1, 2022
A collection of native SwiftUI layouts (iOS 16+)

SwiftUILayouts A library of commonly requested layouts. Implemented using SwiftUI's native layout system. NOTE: SwiftUILayouts requires iOS 16 or abov

Apptek Studios 25 Dec 26, 2022
A fancy collection style view controller that was inspired by this Profile Card mockup

JFCardSelectionViewController A fancy collection style view controller that was inspired by this Profile Card mockup: https://dribbble.com/shots/14584

Jeremy Fox 430 Dec 5, 2022
A collection of common SwiftUI and UIKit utilities.

KippleUI A collection of common SwiftUI and UIKit utilities. ⚠️ The code in this library has been made public as-is for the purposes of education, dis

Kipple 10 Sep 2, 2022
A collection of common diagnostics and debugging utilities.

KippleDiagnostics A collection of common diagnostics and debugging utilities. ⚠️ The code in this library has been made public as-is for the purposes

Kipple 10 Sep 2, 2022
ConfettiKit is a custom framework used to add Confetti on your iOS/iPadOS projects.

ConfettiKit is a custom framework used to add Confetti on your iOS/iPadOS projects. The kit provides variety of customisations inorder to design a confetti which matches your project's UI. ConfettiKit makes your work of adding Confetti on your project with just one line of code.

Gokul Nair 14 Sep 27, 2022
A simple project which shows how to pull off custom view controller transitions.

Custom View Controller Transitions This project explains and shows how to make custom view controller transitions in the most simple way possible. Eac

Jordan Morgan 91 Oct 23, 2022
Custom MacBook login screen and pam modules using multipeer connectivity and usb hardware checks with iOS app for sign in.

Custom MacBook login screen and pam modules using multipeer connectivity and usb hardware checks with iOS app for sign in.

null 2 Aug 17, 2022
A custom calculator for deg to rad conversion & the other way round

Lilium Features A custom calculator for deg to rad conversion & the other way round. How to use Slide up the dock and you should see Lilium. An activa

null 2 Nov 20, 2022
SwiftyXPC - a wrapper for Apple’s XPC interprocess communication library that gives it an easy-to-use, idiomatic Swift interface.

SwiftyXPC is a wrapper for Apple’s XPC interprocess communication library that gives it an easy-to-use, idiomatic Swift interface.

null 36 Jan 1, 2023