Custom decoding with property wrapper

Jun 11, 2021 1:02 PM
Jun 11, 2021 12:51 PM

Swift's Codable (Decodable) is very handy for decoding from JSON. We can get to do that without writing the code how decode value.

However, we have to write everything on how decodes if we get one or more exceptions from automatic decoding. It's so disappointing.

We solve this problem with using PropertyWrapper.

let json = """
  "name": "muukii",
  "number": "0.07"
""".data(using: .utf8)!
struct Container: Decodable {

  var name: String
  @CustomDecoding<Decimal, StringToDecimalDecoder> var number: Decimal

enum StringToDecimalDecoder: CustomDecoder {

  enum Error: Swift.Error {
    case unableToCreateDecimalFromStringValue

  typealias Value = Decimal

  static func decode(from decoder: Decoder) throws -> Decimal {
    let value = try decoder.singleValueContainer().decode(String.self)
    guard let decimal = Decimal.init(string: value) else {
      throw Error.unableToCreateDecimalFromStringValue
    return decimal

public protocol CustomDecoder {

  associatedtype Value

  static func decode(from decoder: Decoder) throws -> Value

public struct CustomDecoding<Value, Decoding: CustomDecoder>: Decodable
where Decoding.Value == Value {

  public var wrappedValue: Value

  public init(
    wrappedValue: Value
  ) {
    self.wrappedValue = wrappedValue

  public init(
    from decoder: Decoder
  ) throws {

    let value = try Decoding.decode(from: decoder)
    self.wrappedValue = value