Skip to content

Instantly share code, notes, and snippets.

@hamishknight
Last active March 24, 2021 22:53
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hamishknight/c6d270f7298e4db9e787aecb5b98bcae to your computer and use it in GitHub Desktop.
Save hamishknight/c6d270f7298e4db9e787aecb5b98bcae to your computer and use it in GitHub Desktop.
import Foundation
struct FailableDecodable<Base : Decodable> : Decodable {
let base: Base?
init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
self.base = try? container.decode(Base.self)
}
}
struct FailableCodableArray<Element : Codable> : Codable {
var elements: [Element]
init(from decoder: Decoder) throws {
var container = try decoder.unkeyedContainer()
var elements = [Element]()
if let count = container.count {
elements.reserveCapacity(count)
}
while !container.isAtEnd {
if let element = try container
.decode(FailableDecodable<Element>.self).base {
elements.append(element)
}
}
self.elements = elements
}
func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
try container.encode(elements)
}
}
struct ProductsRoot : Codable {
var products: [GroceryProduct]
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
self.products = try container
.decode(FailableCodableArray<GroceryProduct>.self, forKey: .products)
.elements
}
}
// or...
struct ProductsRoot2 : Codable {
private let _products: FailableCodableArray<GroceryProduct>
var products: [GroceryProduct] {
return _products.elements
}
private enum CodingKeys : String, CodingKey {
case _products = "products"
}
}
struct GroceryProduct : Codable {
var name: String
var points: Int
var description: String?
}
let jsonString = """
{ "products": [
{
"name": "Banana",
"points": 200,
"description": "A banana grown in Ecuador."
},
{
"name": "Orange"
}
]}
"""
let jsonData = Data(jsonString.utf8)
do {
let decoded = try JSONDecoder().decode(ProductsRoot.self, from: jsonData)
print(decoded)
let decoded2 = try JSONDecoder().decode(ProductsRoot2.self, from: jsonData)
print(decoded2)
} catch {
print(error)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment