Last active
May 14, 2018 09:42
-
-
Save shawnthroop/705b90343b791feccd98637d32eaa4c2 to your computer and use it in GitHub Desktop.
Possible typesafe keys and values for representing pnut.io's Raw data
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Foundation | |
let data = """ | |
{ | |
"version": "1.0", | |
"type": "photo", | |
"width": 240, | |
"height": 160, | |
"title": "ZB8T0193", | |
"url": "http://farm4.static.flickr.com/3123/2341623661_7c99f48bbf_m.jpg", | |
"author_name": "Bees", | |
"author_url": "http://www.flickr.com/photos/bees/", | |
"provider_name": "Flickr", | |
"provider_url": "http://www.flickr.com/", | |
"embeddable_url": "http://www.flickr.com/photos/bees/2341623661/" | |
} | |
""".data(using: .utf8)! | |
do { | |
dump(try JSONDecoder().decode(RawValue.self, from: data)) | |
} catch { | |
print(error) | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Swift 4.1 | |
/// A value representing possible OEmbed response parameters | |
public struct RawKey: Hashable { | |
public let rawValue: String | |
public init(_ rawValue: String) { | |
self.rawValue = rawValue | |
} | |
} | |
extension RawKey: Codable { | |
public init(from decoder: Decoder) throws { | |
let container = try decoder.singleValueContainer() | |
self.init(try container.decode(String.self)) | |
} | |
public func encode(to encoder: Encoder) throws { | |
var container = encoder.singleValueContainer() | |
try container.encode(rawValue) | |
} | |
} | |
extension RawKey: CodingKey { | |
public init?(intValue: Int) { | |
return nil | |
} | |
public var intValue: Int? { | |
return nil | |
} | |
public init?(stringValue: String) { | |
self.init(stringValue) | |
} | |
public var stringValue: String { | |
return rawValue | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Swift 4.1 | |
/// A value representing possible OEmbed response values. | |
private enum RawValue: Equatable { | |
case integer(Int) | |
case string(String) | |
case array([RawValue]) | |
case dictionary([RawKey: RawValue]) | |
} | |
extension RawValue: Decodable { | |
init(from decoder: Decoder) throws { | |
var object: RawValue? | |
if let container = try? decoder.container(keyedBy: RawKey.self) { | |
object = try RawValue(from: container) | |
} else if let container = try? decoder.singleValueContainer() { | |
object = try RawValue(from: container) | |
} | |
guard let this = object else { | |
throw DecodingError.rawValueDataCorrupted(codingPath: decoder.codingPath) | |
} | |
self = this | |
} | |
} | |
private extension RawValue { | |
init?(from container: SingleValueDecodingContainer) throws { | |
if let value = try container.decode(possible: String.self) { | |
self = .string(value) | |
} else if let value = try container.decode(possible: Int.self) { | |
self = .integer(value) | |
} else if let value = try container.decode(possible: [RawValue].self) { | |
self = .array(value) | |
} else { | |
return nil | |
} | |
} | |
init(from container: KeyedDecodingContainer<RawKey>) throws { | |
let value = try container.allKeys.reduce(into: [RawKey: RawValue]()) { values, key in | |
values[key] = try container.decode(RawValue.self, forKey: key) | |
} | |
self = .dictionary(value) | |
} | |
} | |
private extension SingleValueDecodingContainer { | |
func decode<T>(possible type: T.Type) throws -> T? where T: Decodable { | |
var value: T? | |
do { | |
value = try decode(T.self) | |
} catch let error as DecodingError { | |
guard case .typeMismatch(_) = error else { | |
throw error | |
} | |
} catch { | |
throw error | |
} | |
return value | |
} | |
} | |
private extension DecodingError { | |
static func rawValueDataCorrupted(codingPath path: [CodingKey]) -> DecodingError { | |
return .dataCorrupted(Context(codingPath: path, debugDescription: "Unable to decode RawValue")) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment