Skip to content

Instantly share code, notes, and snippets.

@hamishknight
Last active June 10, 2017 21:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hamishknight/6840442a3195da64bb01004f6bc6c31e to your computer and use it in GitHub Desktop.
Save hamishknight/6840442a3195da64bb01004f6bc6c31e to your computer and use it in GitHub Desktop.
import Foundation
struct AnyCodingKey : CodingKey {
let stringValue: String
let intValue: Int?
init(_ base: CodingKey) {
self.stringValue = base.stringValue
self.intValue = base.intValue
}
init?(intValue: Int) {
self.intValue = intValue
self.stringValue = String(intValue)
}
init?(stringValue: String) {
self.stringValue = stringValue
self.intValue = Int(stringValue)
}
}
extension JSONDecoder {
private static let rootKeyPathKey = CodingUserInfoKey(rawValue: "rootKeyPath")!
private struct KeyPathDecodable<Value : Decodable> : Decodable {
let value: Value
init(from decoder: Decoder) throws {
let keyPath = decoder.userInfo[JSONDecoder.rootKeyPathKey] as! [AnyCodingKey]
var container = try decoder.container(keyedBy: AnyCodingKey.self)
for key in keyPath.dropLast() {
container = try container.nestedContainer(keyedBy: AnyCodingKey.self, forKey: key)
}
self.value = try container.decode(Value.self, forKey: keyPath.last!)
}
}
func decode<T : Decodable>(_ type: T.Type, rootKeyPath: [AnyCodingKey], from data: Data) throws -> T {
userInfo[JSONDecoder.rootKeyPathKey] = rootKeyPath
return try decode(KeyPathDecodable<T>.self, from: data).value
}
}
struct Address : Codable {
var street: String
var zip: String
var city: String
var state: String
}
let jsonString = """
{
"foo": "hello world",
"house": {
"bar": 67.8,
"address": {
"state": "California",
"street": "Apple Bay Street",
"zip": "94608",
"city": "Emeryville"
}
}
}
"""
enum PersonToAddressCodingKeys : CodingKey {
case house, address
}
let jsonData = jsonString.data(using: .utf8)!
do {
print(try JSONDecoder().decode(Address.self, rootKeyPath: [PersonToAddressCodingKeys.house, .address].map(AnyCodingKey.init), from: jsonData))
} catch {
print(error)
}
// Address(street: "Apple Bay Street", zip: "94608", city: "Emeryville", state: "California")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment