Skip to content

Instantly share code, notes, and snippets.

@woolsweater
Created February 7, 2020 21:03
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 woolsweater/91fa99cc384a00bd6bc569ed49458d0e to your computer and use it in GitHub Desktop.
Save woolsweater/91fa99cc384a00bd6bc569ed49458d0e to your computer and use it in GitHub Desktop.
import Foundation
/**
A decodable type that expects its data to be enclosed in a
keyed container.
For example, using JSON, a `User` object might be delivered
inside another object, with `"user"` as the key:
```
{ "user" : { "name" : "Alice", "rank" : "Colonel" } }
```
*/
protocol EnvelopeDecodable : Decodable {
/** The key for this type in the enclosing container. */
static var contentsKey: String { get }
}
/**
Decodable representation for another decodable type
that is delivered as a nested object in a keyed container.
*/
struct Envelope<T : EnvelopeDecodable> : Decodable {
/** The wrapped value that we actually want to extract. */
let contents: T
private enum CodingKeys : CodingKey {
case contents
var stringValue: String { T.contentsKey }
}
}
// Example:
struct User : EnvelopeDecodable {
static let contentsKey = "user"
let name: String
let rank: String
let favoriteCereal: String
}
let json = """
{
"user" : {
"name" : "Alice",
"rank" : "Colonel",
"favoriteCereal" : "Corn flakes"
}
}
""".data(using: .utf8)!
let response = try! JSONDecoder().decode(Envelope<User>.self, from: json)
print(response.contents) // User(name: "Alice", rank: "Colonel", favoriteCereal: "Corn flakes")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment