0
0
iOS Swiftmobile~20 mins

Custom decoder configuration in iOS Swift - Practice Problems & Coding Challenges

Choose your learning style9 modes available
Challenge - 5 Problems
🎖️
Custom Decoder Master
Get all challenges correct to earn this badge!
Test your skills under time pressure!
📝 Syntax
intermediate
2:00remaining
Correct syntax for custom decoder init
Which option correctly implements a custom initializer for decoding a Swift struct with a nested container?
iOS Swift
struct User: Decodable {
  let name: String
  let age: Int

  enum CodingKeys: String, CodingKey {
    case info
  }

  enum InfoKeys: String, CodingKey {
    case name
    case age
  }

  init(from decoder: Decoder) throws {
    let container = try decoder.container(keyedBy: CodingKeys.self)
    let infoContainer = try container.nestedContainer(keyedBy: InfoKeys.self, forKey: .info)
    name = try infoContainer.decode(String.self, forKey: .name)
    age = try infoContainer.decode(Int.self, forKey: .age)
  }
}
A
init(from decoder: Decoder) throws {
  let container = try decoder.unkeyedContainer()
  name = try container.decode(String.self)
  age = try container.decode(Int.self)
}
B
init(from decoder: Decoder) throws {
  let container = try decoder.container(keyedBy: InfoKeys.self)
  name = try container.decode(String.self, forKey: .name)
  age = try container.decode(Int.self, forKey: .age)
}
C
init(from decoder: Decoder) throws {
  let container = try decoder.container(keyedBy: CodingKeys.self)
  name = try container.decode(String.self, forKey: .name)
  age = try container.decode(Int.self, forKey: .age)
}
D
init(from decoder: Decoder) throws {
  let container = try decoder.container(keyedBy: CodingKeys.self)
  let infoContainer = try container.nestedContainer(keyedBy: InfoKeys.self, forKey: .info)
  name = try infoContainer.decode(String.self, forKey: .name)
  age = try infoContainer.decode(Int.self, forKey: .age)
}
Attempts:
2 left
💡 Hint
Remember to access the nested container using the correct key and key type.
ui_behavior
intermediate
1:30remaining
Effect of missing key in custom decoder
What happens if a required key is missing when decoding with a custom decoder initializer in Swift?
iOS Swift
struct Product: Decodable {
  let id: Int
  let name: String

  enum CodingKeys: String, CodingKey {
    case id
    case name
  }

  init(from decoder: Decoder) throws {
    let container = try decoder.container(keyedBy: CodingKeys.self)
    id = try container.decode(Int.self, forKey: .id)
    name = try container.decode(String.self, forKey: .name)
  }
}

// JSON missing 'name' key
let jsonData = "{\"id\": 101}".data(using: .utf8)!
AThe decoding succeeds and 'name' is set to an empty string.
BThe decoding succeeds and 'name' is set to nil.
CThe decoding throws a DecodingError.keyNotFound error at runtime.
DThe decoding silently ignores the missing key and sets default values.
Attempts:
2 left
💡 Hint
Think about how Swift Decodable handles missing required keys by default.
lifecycle
advanced
2:30remaining
Custom decoder with date decoding strategy
How can you configure a JSONDecoder to decode dates in a custom format when decoding a struct with a custom decoder initializer?
iOS Swift
struct Event: Decodable {
  let title: String
  let date: Date

  enum CodingKeys: String, CodingKey {
    case title
    case date
  }

  init(from decoder: Decoder) throws {
    let container = try decoder.container(keyedBy: CodingKeys.self)
    title = try container.decode(String.self, forKey: .title)
    date = try container.decode(Date.self, forKey: .date)
  }
}

let decoder = JSONDecoder()
// Configure decoder here for custom date format
A
decoder.dateDecodingStrategy = .custom { decoder in
  let container = try decoder.singleValueContainer()
  let dateString = try container.decode(String.self)
  let formatter = DateFormatter()
  formatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
  guard let date = formatter.date(from: dateString) else {
    throw DecodingError.dataCorruptedError(in: container, debugDescription: "Invalid date format")
  }
  return date
}
Bdecoder.dateDecodingStrategy = .formatted(DateFormatter())
Cdecoder.dateDecodingStrategy = .secondsSince1970
Ddecoder.dateDecodingStrategy = .iso8601
Attempts:
2 left
💡 Hint
Use a custom closure to parse the date string with your own format.
navigation
advanced
2:00remaining
Decoding nested JSON with optional nested container
Given a JSON where a nested object may be missing, how do you safely decode an optional nested container in a custom decoder initializer?
iOS Swift
struct Profile: Decodable {
  let username: String
  let address: Address?

  struct Address: Decodable {
    let city: String
    let zip: String
  }

  enum CodingKeys: String, CodingKey {
    case username
    case address
  }

  init(from decoder: Decoder) throws {
    let container = try decoder.container(keyedBy: CodingKeys.self)
    username = try container.decode(String.self, forKey: .username)
    if container.contains(.address) {
      let addressContainer = try container.nestedContainer(keyedBy: AddressCodingKeys.self, forKey: .address)
      let city = try addressContainer.decode(String.self, forKey: .city)
      let zip = try addressContainer.decode(String.self, forKey: .zip)
      address = Address(city: city, zip: zip)
    } else {
      address = nil
    }
  }

  enum AddressCodingKeys: String, CodingKey {
    case city
    case zip
  }
}
ADecode address as optional directly with decodeIfPresent(Address.self, forKey: .address).
BUse try? container.nestedContainer(keyedBy: AddressCodingKeys.self, forKey: .address) and unwrap optional.
CForce unwrap nested container with try container.nestedContainer(keyedBy: AddressCodingKeys.self, forKey: .address) without checking.
DUse container.contains(.address) to check before decoding nested container.
Attempts:
2 left
💡 Hint
Swift Decodable supports decoding optional nested objects directly.
🔧 Debug
expert
3:00remaining
Identify the cause of decoding failure in custom decoder
Why does the following custom decoder initializer fail to decode the JSON correctly?
iOS Swift
struct Item: Decodable {
  let id: Int
  let tags: [String]

  enum CodingKeys: String, CodingKey {
    case id
    case tags
  }

  init(from decoder: Decoder) throws {
    let container = try decoder.container(keyedBy: CodingKeys.self)
    id = try container.decode(Int.self, forKey: .id)
    let tagsContainer = try container.nestedUnkeyedContainer(forKey: .tags)
    tags = try tagsContainer.decode([String].self)
  }
}

// JSON example: {"id": 5, "tags": ["swift", "ios"]}
AnestedUnkeyedContainer returns an UnkeyedDecodingContainer which cannot decode an array directly.
Bdecode([String].self) is invalid inside a nestedUnkeyedContainer; should decode elements one by one.
CThe code should use decodeIfPresent instead of decode for tags.
DThe JSON format is invalid for decoding tags as an array.
Attempts:
2 left
💡 Hint
Unkeyed containers decode elements one at a time, not whole arrays.