<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><br class=""><div><blockquote type="cite" class=""><div class="">On Jun 17, 2017, at 10:07 PM, Chris Anderson via swift-users <<a href="mailto:swift-users@swift.org" class="">swift-users@swift.org</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><meta http-equiv="Content-Type" content="text/html charset=utf-8" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class="">Say I have a JSON object such as:<div class=""><br class=""></div><div class=""><div style="margin: 0px; line-height: normal; font-family: Menlo; color: rgb(209, 47, 27); background-color: rgb(255, 255, 255);" class=""> {</div><div style="margin: 0px; line-height: normal; font-family: Menlo; color: rgb(209, 47, 27); background-color: rgb(255, 255, 255);" class=""> "id": "4yq6txdpfadhbaqnwp3",</div><div style="margin: 0px; line-height: normal; font-family: Menlo; color: rgb(209, 47, 27); background-color: rgb(255, 255, 255);" class=""> "email": "<a href="mailto:john.doe@example.com" class="">john.doe@example.com</a>",</div><div style="margin: 0px; line-height: normal; font-family: Menlo; color: rgb(209, 47, 27); background-color: rgb(255, 255, 255);" class=""> "name":"John Doe",</div><div style="margin: 0px; line-height: normal; font-family: Menlo; color: rgb(209, 47, 27); background-color: rgb(255, 255, 255);" class=""> "metadata": {</div><div style="margin: 0px; line-height: normal; font-family: Menlo; color: rgb(209, 47, 27); background-color: rgb(255, 255, 255);" class=""> "link_id": "linked-id",</div><div style="margin: 0px; line-height: normal; font-family: Menlo; color: rgb(209, 47, 27); background-color: rgb(255, 255, 255);" class=""> "buy_count": 4</div><div style="margin: 0px; line-height: normal; font-family: Menlo; color: rgb(209, 47, 27); background-color: rgb(255, 255, 255);" class=""> }</div><div style="margin: 0px; line-height: normal; font-family: Menlo; color: rgb(209, 47, 27); background-color: rgb(255, 255, 255);" class=""> }</div></div><div style="margin: 0px; line-height: normal; font-family: Menlo; color: rgb(209, 47, 27); background-color: rgb(255, 255, 255);" class=""><br class=""></div><div style="margin: 0px; line-height: normal; font-family: Menlo; color: rgb(209, 47, 27); background-color: rgb(255, 255, 255);" class=""><span style="font-family: Helvetica;" class="">And with a struct of:</span></div><div style="margin: 0px; line-height: normal; font-family: Menlo; color: rgb(209, 47, 27); background-color: rgb(255, 255, 255);" class=""><span style="font-family: Helvetica;" class=""><br class=""></span></div><div style="margin: 0px; line-height: normal; background-color: rgb(255, 255, 255);" class=""><div style="font-family: Menlo; margin: 0px; line-height: normal;" class=""><span style="color: #ba2da2" class="">struct</span> User: <span style="color: #703daa" class="">Codable</span> {</div><div style="font-family: Menlo; margin: 0px; line-height: normal;" class=""> <span style="color: #ba2da2" class="">var</span> id: <span style="color: #703daa" class="">String</span></div><div style="font-family: Menlo; margin: 0px; line-height: normal;" class=""> <span style="color: #ba2da2" class="">var</span> email: <span style="color: #703daa" class="">String</span></div><div style="font-family: Menlo; margin: 0px; line-height: normal;" class=""> <span style="color: #ba2da2" class="">var</span> name: <span style="color: #703daa" class="">String</span></div><div style="font-family: Menlo; color: rgb(0, 132, 0); margin: 0px; line-height: normal;" class=""><span style="" class="">}</span></div><div style="font-family: Menlo; color: rgb(0, 132, 0); margin: 0px; line-height: normal;" class=""><br class=""></div><div style="margin: 0px; line-height: normal;" class=""><div style="margin: 0px; line-height: normal;" class="">How can I decode the `metadata` field into a Dictionary?</div><div style="margin: 0px; line-height: normal;" class=""><br class=""></div><div style="margin: 0px; line-height: normal;" class="">I’ve tried doing things such as, in my struct,</div><div style="margin: 0px; line-height: normal;" class=""><br class=""></div><div style="margin: 0px; line-height: normal;" class=""><span style="font-family: Menlo; color: rgb(186, 45, 162);" class="">var</span><span style="font-family: Menlo;" class=""> </span><span style="font-family: Menlo;" class="">metadata:</span><span style="font-family: Menlo;" class=""> </span><span style="font-family: Menlo; color: rgb(112, 61, 170);" class="">Dictionary</span></div><div style="margin: 0px; line-height: normal;" class=""><br class=""></div><div style="margin: 0px; line-height: normal;" class="">or</div><div style="margin: 0px; line-height: normal;" class=""><span style="font-family: Menlo; color: rgb(112, 61, 170);" class=""><br class=""></span></div><div style="margin: 0px; line-height: normal;" class=""><div style="margin: 0px; line-height: normal;" class=""><span style="font-family: Menlo; color: rgb(186, 45, 162);" class="">var</span><span style="font-family: Menlo;" class=""> </span><span style="font-family: Menlo;" class="">metadata:</span><span style="font-family: Menlo;" class=""> </span><span style="font-family: Menlo; color: rgb(112, 61, 170);" class="">[String: Any]</span></div><div style="margin: 0px; line-height: normal;" class=""><span style="font-family: Menlo; color: rgb(112, 61, 170);" class=""><br class=""></span></div><div style="margin: 0px; line-height: normal;" class="">But I get the error </div><div style="margin: 0px; line-height: normal;" class=""><br class=""></div><div style="margin: 0px; line-height: normal;" class="">MyPlayground.playground:3:7: note: cannot automatically synthesize 'Encodable' because '<<error type>>' does not conform to 'Encodable'</div><div style="margin: 0px; line-height: normal;" class=""> var metadata: Dictionary<span style="font-family: Menlo; color: rgb(112, 61, 170);" class=""> </span></div><div style="margin: 0px; line-height: normal;" class=""><span style="font-family: Menlo; color: rgb(112, 61, 170);" class=""><br class=""></span></div><div style="margin: 0px; line-height: normal;" class="">A meta or metadata field on many APIs (such as <a href="http://www.stripe.com/" class="">www.stripe.com</a>) can contain whatever you want, and I still want to be able to process it on the Swift end. How can I store that meta data field into a Dictionary that I can parse apart manually after?</div></div></div></div></div></div></blockquote><br class=""></div><div>It’s possible, but you have to do most of the work yourself because you the compiler can’t create implementations for you. See below for a possible implementation. Note that I just ignore types I don’t handle. I also took a stab at doing something general in this gist (<a href="https://gist.github.com/kenada/069e121371eb8db41231edfcd4bd14a8" class="">https://gist.github.com/kenada/069e121371eb8db41231edfcd4bd14a8</a>), but it doesn’t implement very robust error handling or support encoding. It also doesn’t flatten down to Any/[Any]/[String: Any] (leaving it up to the user to destructure the enum).</div><br class=""><div class=""><div class=""><font face="Menlo" class="">import Foundation</font></div><div class=""><font face="Menlo" class=""><br class=""></font></div><div class=""><font face="Menlo" class="">struct User: Codable {</font></div><div class=""><font face="Menlo" class=""> var id: String</font></div><div class=""><font face="Menlo" class=""> var email: String</font></div><div class=""><font face="Menlo" class=""> var name: String</font></div><div class=""><font face="Menlo" class=""> var metadata: [String: Any]</font></div><div class=""><font face="Menlo" class=""><br class=""></font></div><div class=""><font face="Menlo" class=""> init(from decoder: Decoder) throws {</font></div><div class=""><font face="Menlo" class=""> let container = try decoder.container(keyedBy: StaticCodingKeys.self)</font></div><div class=""><font face="Menlo" class=""> self.id = try container.decode(String.self, forKey: .id)</font></div><div class=""><font face="Menlo" class=""> self.email = try container.decode(String.self, forKey: .email)</font></div><div class=""><font face="Menlo" class=""> self.name = try container.decode(String.self, forKey: .name)</font></div><div class=""><font face="Menlo" class=""> self.metadata = try User.decodeMetadata(from: container.superDecoder(forKey: .metadata))</font></div><div class=""><font face="Menlo" class=""> }</font></div><div class=""><font face="Menlo" class=""><br class=""></font></div><div class=""><font face="Menlo" class=""> func encode(to encoder: Encoder) throws {</font></div><div class=""><font face="Menlo" class=""> var container = encoder.container(keyedBy: StaticCodingKeys.self)</font></div><div class=""><font face="Menlo" class=""> try container.encode(self.id, forKey: .id)</font></div><div class=""><font face="Menlo" class=""> try container.encode(self.email, forKey: .email)</font></div><div class=""><font face="Menlo" class=""> try container.encode(self.name, forKey: .name)</font></div><div class=""><font face="Menlo" class=""> try encodeMetadata(to: container.superEncoder(forKey: .metadata))</font></div><div class=""><font face="Menlo" class=""> }</font></div><div class=""><font face="Menlo" class=""><br class=""></font></div><div class=""><font face="Menlo" class=""> static func decodeMetadata(from decoder: Decoder) throws -> [String: Any] {</font></div><div class=""><font face="Menlo" class=""> let container = try decoder.container(keyedBy: DynamicCodingKeys.self)</font></div><div class=""><font face="Menlo" class=""> var result: [String: Any] = [:]</font></div><div class=""><font face="Menlo" class=""> for key in container.allKeys {</font></div><div class=""><font face="Menlo" class=""> if let double = try? container.decode(Double.self, forKey: key) {</font></div><div class=""><font face="Menlo" class=""> result[key.stringValue] = double</font></div><div class=""><font face="Menlo" class=""> } else if let string = try? container.decode(String.self, forKey: key) {</font></div><div class=""><font face="Menlo" class=""> result[key.stringValue] = string</font></div><div class=""><font face="Menlo" class=""> }</font></div><div class=""><font face="Menlo" class=""> }</font></div><div class=""><font face="Menlo" class=""> return result</font></div><div class=""><font face="Menlo" class=""> }</font></div><div class=""><font face="Menlo" class=""><br class=""></font></div><div class=""><font face="Menlo" class=""> func encodeMetadata(to encoder: Encoder) throws {</font></div><div class=""><font face="Menlo" class=""> var container = encoder.container(keyedBy: DynamicCodingKeys.self)</font></div><div class=""><font face="Menlo" class=""> for (key, value) in metadata {</font></div><div class=""><font face="Menlo" class=""> switch value {</font></div><div class=""><font face="Menlo" class=""> case let double as Double:</font></div><div class=""><font face="Menlo" class=""> try container.encode(double, forKey: DynamicCodingKeys(stringValue: key)!)</font></div><div class=""><font face="Menlo" class=""> case let string as String:</font></div><div class=""><font face="Menlo" class=""> try container.encode(string, forKey: DynamicCodingKeys(stringValue: key)!)</font></div><div class=""><font face="Menlo" class=""> default:</font></div><div class=""><font face="Menlo" class=""> fatalError("unexpected type")</font></div><div class=""><font face="Menlo" class=""> }</font></div><div class=""><font face="Menlo" class=""> }</font></div><div class=""><font face="Menlo" class=""> }</font></div><div class=""><font face="Menlo" class=""><br class=""></font></div><div class=""><font face="Menlo" class=""> private enum StaticCodingKeys: String, CodingKey {</font></div><div class=""><font face="Menlo" class=""> case id, email, name, metadata</font></div><div class=""><font face="Menlo" class=""> }</font></div><div class=""><font face="Menlo" class=""><br class=""></font></div><div class=""><font face="Menlo" class=""> private struct DynamicCodingKeys: CodingKey {</font></div><div class=""><font face="Menlo" class=""> var stringValue: String</font></div><div class=""><font face="Menlo" class=""><br class=""></font></div><div class=""><font face="Menlo" class=""> init?(stringValue: String) {</font></div><div class=""><font face="Menlo" class=""> self.stringValue = stringValue</font></div><div class=""><font face="Menlo" class=""> }</font></div><div class=""><font face="Menlo" class=""><br class=""></font></div><div class=""><font face="Menlo" class=""> var intValue: Int?</font></div><div class=""><font face="Menlo" class=""><br class=""></font></div><div class=""><font face="Menlo" class=""> init?(intValue: Int) {</font></div><div class=""><font face="Menlo" class=""> self.init(stringValue: "")</font></div><div class=""><font face="Menlo" class=""> self.intValue = intValue</font></div><div class=""><font face="Menlo" class=""> }</font></div><div class=""><font face="Menlo" class=""> }</font></div><div class=""><font face="Menlo" class="">}</font></div><div class=""><font face="Menlo" class=""><br class=""></font></div><div class=""><font face="Menlo" class="">let userJson = """</font></div><div class=""><font face="Menlo" class=""> {</font></div><div class=""><font face="Menlo" class=""> "id": "4yq6txdpfadhbaqnwp3",</font></div><div class=""><font face="Menlo" class=""> "email": "<a href="mailto:john.doe@example.com" class="">john.doe@example.com</a>",</font></div><div class=""><font face="Menlo" class=""> "name":"John Doe",</font></div><div class=""><font face="Menlo" class=""> "metadata": {</font></div><div class=""><font face="Menlo" class=""> "link_id": "linked-id",</font></div><div class=""><font face="Menlo" class=""> "buy_count": 4</font></div><div class=""><font face="Menlo" class=""> }</font></div><div class=""><font face="Menlo" class=""> }</font></div><div class=""><font face="Menlo" class="">""".data(using: .utf8)!</font></div><div class=""><font face="Menlo" class=""><br class=""></font></div><div class=""><font face="Menlo" class="">let decoder = JSONDecoder()</font></div><div class=""><font face="Menlo" class="">let user = try! decoder.decode(User.self, from: userJson)</font></div><div class=""><font face="Menlo" class="">print(user)</font></div><div class=""><font face="Menlo" class="">// Prints: User(id: "4yq6txdpfadhbaqnwp3", email: "<a href="mailto:john.doe@example.com" class="">john.doe@example.com</a>", name: "John Doe", metadata: ["buy_count": 4.0, "link_id": "linked-id"])</font></div><div class=""><font face="Menlo" class=""><br class=""></font></div><div class=""><font face="Menlo" class="">let encoder = JSONEncoder()</font></div><div class=""><font face="Menlo" class="">let data = try! encoder.encode(user)</font></div><div class=""><font face="Menlo" class="">print(String(data: data, encoding: .utf8)!)</font></div></div><div class=""><font face="Menlo" class="">// Prints: {"email":"<a href="mailto:john.doe@example.com" class="">john.doe@example.com</a>","id":"4yq6txdpfadhbaqnwp3","metadata":{"link_id":"linked-id","buy_count":4},"name":"John Doe"}</font></div><div class=""><br class=""></div><div class="">-- </div><div class="">Randy Eckenrode</div></body></html>