Skip to content

Instantly share code, notes, and snippets.

@SlaunchaMan
Created October 24, 2018 19:57
Show Gist options
  • Save SlaunchaMan/1cba8f9ba210a04895b25a73e08df1df to your computer and use it in GitHub Desktop.
Save SlaunchaMan/1cba8f9ba210a04895b25a73e08df1df to your computer and use it in GitHub Desktop.
Decoding items when one of them may not decode successfully.
extension KeyedDecodingContainer {
/// An item that cannot be decoded. Used in `compactDecode(arrayOf:forKey:)`
/// to represent items that could not be decoded.
private struct UndecodableItem: Decodable {}
/// Attempts to decode an array of type `T`. If an individual item in the
/// array fails to decode, these errors are not passed on to the caller;
/// instead, they are not included in the final array.
///
/// - Parameters:
/// - type: The type to decode.
/// - key: The key to decode into an array of type `T`.
/// - Returns: An array of type `[T]` containing all of the successfully-
/// decoded items.
/// - Throws: This method will only throw errors that occur outside of
/// decoding individual items; for instance, if the item at `key`
/// is not an array.
func compactDecode<T: Decodable>(arrayOf type: T.Type,
forKey key: K) throws -> [T] {
guard contains(key) else { return [] }
var container = try self.nestedUnkeyedContainer(forKey: key)
var decodedItems = [T]()
while !container.isAtEnd {
if let decodedItem = try? container.decode(type) {
decodedItems.append(decodedItem)
} else {
// To get the container to advance, it must decode *something*,
// so decode an empty struct.
_ = try container.decode(UndecodableItem.self)
}
}
return decodedItems
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment