<div dir="ltr"><div dir="ltr" class="gmail_msg"><div dir="ltr" class="gmail_msg">Hi Itai,<div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_quote gmail_msg"></div></div></div><div dir="ltr" class="gmail_msg"><div dir="ltr" class="gmail_msg"><div class="gmail_quote gmail_msg"><div dir="ltr" class="gmail_msg">On Tue, Mar 21, 2017 at 1:03 PM Itai Ferber <<a href="mailto:iferber@apple.com" class="gmail_msg" target="_blank">iferber@apple.com</a>> wrote:<br class="gmail_msg"></div><blockquote class="gmail_quote gmail_msg" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><u class="gmail_msg"></u>
<div class="gmail_msg">
<div style="font-family:sans-serif" class="gmail_msg"><div style="white-space:normal" class="gmail_msg">
<p dir="auto" class="gmail_msg">Hi Colin,</p>
<p dir="auto" class="gmail_msg">Thanks for your comments! Are you talking about <code style="background-color:#f7f7f7;border-radius:3px;margin:0;padding:0 0.4em" bgcolor="#F7F7F7" class="gmail_msg">Codable</code> synthesis, or encoding in general?</p></div></div></div></blockquote></div></div></div><div dir="ltr" class="gmail_msg"><div dir="ltr" class="gmail_msg"><div class="gmail_quote gmail_msg"><div class="gmail_msg">Yeah, I meant specifically in the case where things are synthesized automatically. As you point out below, if someone implements a custom Codeable instance, all bets are off. </div></div></div></div><div dir="ltr" class="gmail_msg"><div dir="ltr" class="gmail_msg"><div class="gmail_quote gmail_msg"><blockquote class="gmail_quote gmail_msg" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div class="gmail_msg"><div style="font-family:sans-serif" class="gmail_msg"><div style="white-space:normal" class="gmail_msg">
<p dir="auto" class="gmail_msg">On 21 Mar 2017, at 8:44, Colin Barrett wrote:</p>
<p dir="auto" class="gmail_msg"></p></div></div></div><div class="gmail_msg"><div style="font-family:sans-serif" class="gmail_msg">
<div style="white-space:normal" class="gmail_msg"><blockquote style="border-left:2px solid #777;color:#777;margin:0 0 5px;padding-left:5px" class="gmail_msg"><p dir="auto" class="gmail_msg">Hi Itai,<br class="gmail_msg">
<br class="gmail_msg">
Glad to see these proposal! I'm curious, have you or the other Swift folks<br class="gmail_msg">
thought about how *users* of these new Codable protocols will interact with<br class="gmail_msg">
resilience domains?<br class="gmail_msg">
<br class="gmail_msg">
What I mean is that what appear to be private or internal identifiers, and<br class="gmail_msg">
thus changeable at will, may actually be fragile in that changing them will<br class="gmail_msg">
break the ability to decode archives encoded by previous versions.<br class="gmail_msg">
<br class="gmail_msg">
Making this safer could mean:<br class="gmail_msg">
- Encoding only public properties</p>
</blockquote></div>
</div></div><div class="gmail_msg"><div style="font-family:sans-serif" class="gmail_msg"><div style="white-space:normal" class="gmail_msg">
<p dir="auto" class="gmail_msg">Unfortunately, property accessibility in code does not always map 1-to-1 with accessibility for archival (nor do I think they should be tied to one another).<br class="gmail_msg">
There are certainly cases where you’d want to include private information in an archive, but that is not useful to expose to external clients, e.g., a struct/class version:</p>
<pre style="background-color:#f7f7f7;border-radius:5px 5px 5px 5px;margin-left:15px;margin-right:15px;max-width:90vw;overflow-x:auto;padding:5px;color:black" bgcolor="#F7F7F7" class="gmail_msg"><code style="background-color:#f7f7f7;border-radius:3px;margin:0;padding:0" bgcolor="#F7F7F7" class="gmail_msg"><span style="color:#008800;font-weight:bold" class="gmail_msg">public</span> <span style="color:#008800;font-weight:bold" class="gmail_msg">struct</span> <span style="color:#bb0066;font-weight:bold" class="gmail_msg">MyFoo</span> {
<span style="color:#888888" class="gmail_msg">// Should be encoded.</span>
<span style="color:#008800;font-weight:bold" class="gmail_msg">public</span> <span style="color:#008800;font-weight:bold" class="gmail_msg">var</span> <span style="color:#996633" class="gmail_msg">title</span>: <span style="color:#007020" class="gmail_msg">String</span>
<span style="color:#008800;font-weight:bold" class="gmail_msg">public</span> <span style="color:#008800;font-weight:bold" class="gmail_msg">var</span> <span style="color:#996633" class="gmail_msg">identifier</span>: <span style="color:#007020" class="gmail_msg">Int</span>
<span style="color:#888888" class="gmail_msg">// This should be encoded too — in case the struct changes in the</span>
<span style="color:#888888" class="gmail_msg">// future, want to be able to refer to the payload version.</span>
<span style="color:#008800;font-weight:bold" class="gmail_msg">private</span> <span style="color:#008800;font-weight:bold" class="gmail_msg">let</span> <span style="color:#996633" class="gmail_msg">version</span> = <span style="color:#6600ee;font-weight:bold" class="gmail_msg">1.0</span>
}
</code></pre>
<p dir="auto" class="gmail_msg">Of course, there can also be public properties that you don’t find useful to encode. At the moment, I’m not sure there’s a much better answer than "the author of the code will have to think about the representation of their data"; even if there were an easier way to annotate "I definitely want this to be archived"/"I definitely don’t want this to be archived", the annotation would still need to be manual.</p>
<p dir="auto" class="gmail_msg">(The above applies primarily in the case of <code style="background-color:#f7f7f7;border-radius:3px;margin:0;padding:0 0.4em" bgcolor="#F7F7F7" class="gmail_msg">Codable</code> synthesis; when implementing <code style="background-color:#f7f7f7;border-radius:3px;margin:0;padding:0 0.4em" bgcolor="#F7F7F7" class="gmail_msg">Codable</code> manually I don’t think the compiler should ever prevent you from doing what you need.)</p>
<p dir="auto" class="gmail_msg"></p></div></div></div><div class="gmail_msg"><div style="font-family:sans-serif" class="gmail_msg">
<div style="white-space:normal" class="gmail_msg"><blockquote style="border-left:2px solid #777;color:#777;margin:0 0 5px;padding-left:5px" class="gmail_msg"><p dir="auto" class="gmail_msg">- Adding some form of indirection (a la ObjC non-fragile ivars?)</p>
</blockquote></div>
</div></div><div class="gmail_msg"><div style="font-family:sans-serif" class="gmail_msg"><div style="white-space:normal" class="gmail_msg">
<p dir="auto" class="gmail_msg">What do you mean by this?</p></div></div></div></blockquote></div></div></div><div dir="ltr" class="gmail_msg"><div dir="ltr" class="gmail_msg"><div class="gmail_quote gmail_msg"><div class="gmail_msg">I'm not sure exactly how or if it would work in-detail, unfortunately, but I know that the ObjC runtime emits symbols which are used to lookup the offset in the object struct for non-fragile ivars. Maybe some similar form of indirection would be useful for encoding non-public ivars. Like I said, don't know exactly how/if that would work, just sharing :)</div></div></div><div dir="ltr" class="gmail_msg"><div class="gmail_quote gmail_msg"></div></div></div><div dir="ltr" class="gmail_msg"><div dir="ltr" class="gmail_msg"><div class="gmail_quote gmail_msg"><div class="gmail_msg"> </div><blockquote class="gmail_quote gmail_msg" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div class="gmail_msg"><div style="font-family:sans-serif" class="gmail_msg"><div style="white-space:normal" class="gmail_msg">
<p dir="auto" class="gmail_msg"></p></div></div></div><div class="gmail_msg"><div style="font-family:sans-serif" class="gmail_msg">
<div style="white-space:normal" class="gmail_msg"><blockquote style="border-left:2px solid #777;color:#777;margin:0 0 5px;padding-left:5px" class="gmail_msg"><p dir="auto" class="gmail_msg">- Compiler warning (or disallowing) changes to properties in certain<br class="gmail_msg">
situations.</p>
</blockquote></div>
</div></div><div class="gmail_msg"><div style="font-family:sans-serif" class="gmail_msg"><div style="white-space:normal" class="gmail_msg">
<p dir="auto" class="gmail_msg">We’ve thought about this with regards to identifying classes uniquely across renaming, moving modules, etc.; this is a resilience problem in general.<br class="gmail_msg">
In order for the compiler to know about changes to your code it’d need to keep state across compilations. While possible, this feels pretty fragile (and potentially not very portable).</p>
<ul class="gmail_msg">
<li class="gmail_msg">Compiler warns about changing a property? Blow away the cache directory!</li>
<li class="gmail_msg">Cloning the code to a new machine for the first time? Hmm, all the warnings went away…</li>
</ul>
<p dir="auto" class="gmail_msg">This would be nice to have, but yes:</p>
<p dir="auto" class="gmail_msg"></p></div></div></div><div class="gmail_msg"><div style="font-family:sans-serif" class="gmail_msg">
<div style="white-space:normal" class="gmail_msg"><blockquote style="border-left:2px solid #777;color:#777;margin:0 0 5px;padding-left:5px" class="gmail_msg"><p dir="auto" class="gmail_msg">I imagine the specifics would need to follow the rest of the plans for<br class="gmail_msg">
resilience.</p>
</blockquote></div>
</div></div><div class="gmail_msg"><div style="font-family:sans-serif" class="gmail_msg"><div style="white-space:normal" class="gmail_msg">
<p dir="auto" class="gmail_msg">specifics on this would likely be in line with the rest of resilience plans for Swift in general.</p></div></div></div></blockquote><div class="gmail_msg"><br class="gmail_msg"></div></div></div></div><div dir="ltr" class="gmail_msg"><div dir="ltr" class="gmail_msg"><div class="gmail_quote gmail_msg"><div class="gmail_msg">Right. Thus my concern about allowing non-public fields to be automatically serialized. The most conservative option would be to only automatically synthesize a Codeable instance for the public members of public types. Seems overly restrictive, so maybe anything goes for internal types, or there's some sort of warning (overridable via an attribute?)</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">I want to emphasize btw that I'm enthusiastic about this proposal in general. The support for integer keys is welcome and, as it's one of my pet projects, eases support for a Cap'n Proto-style serialization format.[1]</div><div class="gmail_msg"><br class="gmail_msg"></div><div class="gmail_msg">-Colin</div></div></div></div><div dir="ltr" class="gmail_msg"><div dir="ltr" class="gmail_msg"><div class="gmail_quote gmail_msg"><div class="gmail_msg"> </div><div class="gmail_msg">[1]: <a href="https://capnproto.org">https://capnproto.org</a></div><div class="gmail_msg"><br></div><blockquote class="gmail_quote gmail_msg" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div class="gmail_msg"><div style="font-family:sans-serif" class="gmail_msg"><div style="white-space:normal" class="gmail_msg">
<p dir="auto" class="gmail_msg"></p></div>
<div style="white-space:normal" class="gmail_msg"><blockquote style="border-left:2px solid #777;color:#777;margin:0 0 5px;padding-left:5px" class="gmail_msg"></blockquote></div></div></div><div class="gmail_msg"><div style="font-family:sans-serif" class="gmail_msg"><div style="white-space:normal" class="gmail_msg"><blockquote style="border-left:2px solid #777;color:#777;margin:0 0 5px;padding-left:5px" class="gmail_msg"><p dir="auto" class="gmail_msg">It's likely that this could be addressed by a future proposal, as for the<br class="gmail_msg">
time being developers can simply "not hold it wrong" ;)<br class="gmail_msg">
<br class="gmail_msg">
Thanks,<br class="gmail_msg">
-Colin<br class="gmail_msg">
<br class="gmail_msg">
On Wed, Mar 15, 2017 at 6:52 PM Itai Ferber via swift-evolution <<br class="gmail_msg">
<a href="mailto:swift-evolution@swift.org" class="gmail_msg" target="_blank">swift-evolution@swift.org</a>> wrote:<br class="gmail_msg">
</p>
</blockquote></div></div></div><div class="gmail_msg"><div style="font-family:sans-serif" class="gmail_msg"><div style="white-space:normal" class="gmail_msg"><blockquote style="border-left:2px solid #777;color:#777;margin:0 0 5px;padding-left:5px" class="gmail_msg"><blockquote style="border-left:2px solid #777;color:#999;margin:0 0 5px;padding-left:5px;border-left-color:#999" class="gmail_msg"><p dir="auto" class="gmail_msg">Hi everyone,<br class="gmail_msg">
<br class="gmail_msg">
The following introduces a new Swift-focused archival and serialization<br class="gmail_msg">
API as part of the Foundation framework. We’re interested in improving the<br class="gmail_msg">
experience and safety of performing archival and serialization, and are<br class="gmail_msg">
happy to receive community feedback on this work.<br class="gmail_msg"></p></blockquote></blockquote></div></div></div><div class="gmail_msg"><div style="font-family:sans-serif" class="gmail_msg"><div style="white-space:normal" class="gmail_msg"><blockquote style="border-left:2px solid #777;color:#777;margin:0 0 5px;padding-left:5px" class="gmail_msg"><blockquote style="border-left:2px solid #777;color:#999;margin:0 0 5px;padding-left:5px;border-left-color:#999" class="gmail_msg"><p dir="auto" class="gmail_msg">
Because of the length of this proposal, the *Appendix* and *Alternatives<br class="gmail_msg">
Considered* sections have been omitted here, but are available in the full<br class="gmail_msg">
proposal <<a href="https://github.com/apple/swift-evolution/pull/639" style="color:#999" class="gmail_msg" target="_blank">https://github.com/apple/swift-evolution/pull/639</a>> on the<br class="gmail_msg">
swift-evolution repo. The full proposal also includes an *Unabridged API* for</p></blockquote></blockquote></div></div></div><div class="gmail_msg"><div style="font-family:sans-serif" class="gmail_msg"><div style="white-space:normal" class="gmail_msg"><blockquote style="border-left:2px solid #777;color:#777;margin:0 0 5px;padding-left:5px" class="gmail_msg"><blockquote style="border-left:2px solid #777;color:#999;margin:0 0 5px;padding-left:5px;border-left-color:#999" class="gmail_msg"><p dir="auto" class="gmail_msg"><br class="gmail_msg">
further consideration.<br class="gmail_msg">
<br class="gmail_msg">
Without further ado, inlined below.<br class="gmail_msg">
<br class="gmail_msg">
— Itai<br class="gmail_msg">
<br class="gmail_msg">
Swift Archival & Serialization<br class="gmail_msg">
<br class="gmail_msg"></p></blockquote></blockquote></div></div></div><div class="gmail_msg"><div style="font-family:sans-serif" class="gmail_msg"><div style="white-space:normal" class="gmail_msg"><blockquote style="border-left:2px solid #777;color:#777;margin:0 0 5px;padding-left:5px" class="gmail_msg"><blockquote style="border-left:2px solid #777;color:#999;margin:0 0 5px;padding-left:5px;border-left-color:#999" class="gmail_msg"><p dir="auto" class="gmail_msg">
- Proposal: SE-NNNN <<a href="https://github.com/apple/swift-evolution/pull/639" style="color:#999" class="gmail_msg" target="_blank">https://github.com/apple/swift-evolution/pull/639</a>><br class="gmail_msg">
- Author(s): Itai Ferber <<a href="https://github.com/itaiferber" style="color:#999" class="gmail_msg" target="_blank">https://github.com/itaiferber</a>>, Michael LeHew<br class="gmail_msg">
<<a href="https://github.com/mlehew" style="color:#999" class="gmail_msg" target="_blank">https://github.com/mlehew</a>>, Tony Parker <<a href="https://github.com/parkera" style="color:#999" class="gmail_msg" target="_blank">https://github.com/parkera</a>><br class="gmail_msg">
- Review Manager: TBD<br class="gmail_msg">
- Status: *Awaiting review*<br class="gmail_msg">
- Associated PRs:<br class="gmail_msg">
- #8124 <<a href="https://github.com/apple/swift/pull/8124" style="color:#999" class="gmail_msg" target="_blank">https://github.com/apple/swift/pull/8124</a>><br class="gmail_msg">
- #8125 <<a href="https://github.com/apple/swift/pull/8125" style="color:#999" class="gmail_msg" target="_blank">https://github.com/apple/swift/pull/8125</a>></p></blockquote></blockquote></div></div></div><div class="gmail_msg"><div style="font-family:sans-serif" class="gmail_msg"><div style="white-space:normal" class="gmail_msg"><blockquote style="border-left:2px solid #777;color:#777;margin:0 0 5px;padding-left:5px" class="gmail_msg"><blockquote style="border-left:2px solid #777;color:#999;margin:0 0 5px;padding-left:5px;border-left-color:#999" class="gmail_msg"><p dir="auto" class="gmail_msg"><br class="gmail_msg">
<br class="gmail_msg">
Introduction<br class="gmail_msg">
<br class="gmail_msg">
Foundation's current archival and serialization APIs (NSCoding,<br class="gmail_msg">
NSJSONSerialization, NSPropertyListSerialization, etc.), while fitting<br class="gmail_msg">
for the dynamism of Objective-C, do not always map optimally into Swift.<br class="gmail_msg">
This document lays out the design of an updated API that improves the<br class="gmail_msg">
developer experience of performing archival and serialization in Swift.<br class="gmail_msg">
<br class="gmail_msg">
Specifically:<br class="gmail_msg">
<br class="gmail_msg"></p></blockquote></blockquote></div></div></div><div class="gmail_msg"><div style="font-family:sans-serif" class="gmail_msg"><div style="white-space:normal" class="gmail_msg"><blockquote style="border-left:2px solid #777;color:#777;margin:0 0 5px;padding-left:5px" class="gmail_msg"><blockquote style="border-left:2px solid #777;color:#999;margin:0 0 5px;padding-left:5px;border-left-color:#999" class="gmail_msg"><p dir="auto" class="gmail_msg">
- It aims to provide a solution for the archival of Swift struct and<br class="gmail_msg">
enum types<br class="gmail_msg">
- It aims to provide a more type-safe solution for serializing to</p></blockquote></blockquote></div></div></div><div class="gmail_msg"><div style="font-family:sans-serif" class="gmail_msg"><div style="white-space:normal" class="gmail_msg"><blockquote style="border-left:2px solid #777;color:#777;margin:0 0 5px;padding-left:5px" class="gmail_msg"><blockquote style="border-left:2px solid #777;color:#999;margin:0 0 5px;padding-left:5px;border-left-color:#999" class="gmail_msg"><p dir="auto" class="gmail_msg"><br class="gmail_msg">
external formats, such as JSON and plist<br class="gmail_msg">
<br class="gmail_msg">
Motivation<br class="gmail_msg">
<br class="gmail_msg">
The primary motivation for this proposal is the inclusion of native Swift<br class="gmail_msg">
enum and struct types in archival and serialization. Currently,<br class="gmail_msg">
developers targeting Swift cannot participate in NSCoding without being<br class="gmail_msg">
willing to abandon enum and structtypes — NSCoding is an @objc protocol,<br class="gmail_msg">
conformance to which excludes non-class types. This is can be limiting in<br class="gmail_msg">
Swift because small enums and structs can be an idiomatic approach to<br class="gmail_msg">
model representation; developers who wish to perform archival have to<br class="gmail_msg">
either forgo the Swift niceties that constructs like enumsprovide, or<br class="gmail_msg">
provide an additional compatibility layer between their "real" types and<br class="gmail_msg">
their archivable types.<br class="gmail_msg">
<br class="gmail_msg">
Secondarily, we would like to refine Foundation's existing serialization<br class="gmail_msg">
APIs (NSJSONSerialization and NSPropertyListSerialization) to better<br class="gmail_msg">
match Swift's strong type safety. From experience, we find that the<br class="gmail_msg">
conversion from the unstructured, untyped data of these formats into<br class="gmail_msg">
strongly-typed data structures is a good fit for archival mechanisms,<br class="gmail_msg">
rather than taking the less safe approach that 3rd-party JSON conversion<br class="gmail_msg">
approaches have taken (described further in an appendix below).<br class="gmail_msg">
<br class="gmail_msg">
We would like to offer a solution to these problems without sacrificing<br class="gmail_msg">
ease of use or type safety.<br class="gmail_msg">
Agenda<br class="gmail_msg">
<br class="gmail_msg">
This proposal is the first stage of three that introduce different facets<br class="gmail_msg">
of a whole Swift archival and serialization API:<br class="gmail_msg">
<br class="gmail_msg"></p></blockquote></blockquote></div></div></div><div class="gmail_msg"><div style="font-family:sans-serif" class="gmail_msg"><div style="white-space:normal" class="gmail_msg"><blockquote style="border-left:2px solid #777;color:#777;margin:0 0 5px;padding-left:5px" class="gmail_msg"><blockquote style="border-left:2px solid #777;color:#999;margin:0 0 5px;padding-left:5px;border-left-color:#999" class="gmail_msg"><p dir="auto" class="gmail_msg">
1. This proposal describes the basis for this API, focusing on the</p></blockquote></blockquote></div></div></div><div class="gmail_msg"><div style="font-family:sans-serif" class="gmail_msg"><div style="white-space:normal" class="gmail_msg"><blockquote style="border-left:2px solid #777;color:#777;margin:0 0 5px;padding-left:5px" class="gmail_msg"><blockquote style="border-left:2px solid #777;color:#999;margin:0 0 5px;padding-left:5px;border-left-color:#999" class="gmail_msg"><p dir="auto" class="gmail_msg"><br class="gmail_msg">
protocols that users adopt and interface with<br class="gmail_msg"></p></blockquote></blockquote></div></div></div><div class="gmail_msg"><div style="font-family:sans-serif" class="gmail_msg"><div style="white-space:normal" class="gmail_msg"><blockquote style="border-left:2px solid #777;color:#777;margin:0 0 5px;padding-left:5px" class="gmail_msg"><blockquote style="border-left:2px solid #777;color:#999;margin:0 0 5px;padding-left:5px;border-left-color:#999" class="gmail_msg"><p dir="auto" class="gmail_msg">
2. The next stage will propose specific API for new encoders<br class="gmail_msg">
3. The final stage will discuss how this new API will interop with</p></blockquote></blockquote></div></div></div><div class="gmail_msg"><div style="font-family:sans-serif" class="gmail_msg"><div style="white-space:normal" class="gmail_msg"><blockquote style="border-left:2px solid #777;color:#777;margin:0 0 5px;padding-left:5px" class="gmail_msg"><blockquote style="border-left:2px solid #777;color:#999;margin:0 0 5px;padding-left:5px;border-left-color:#999" class="gmail_msg"><p dir="auto" class="gmail_msg"><br class="gmail_msg">
NSCoding as it is today<br class="gmail_msg">
<br class="gmail_msg">
SE-NNNN provides stages 2 and 3.<br class="gmail_msg">
Proposed solution<br class="gmail_msg">
<br class="gmail_msg">
We will be introducing the following new types:<br class="gmail_msg">
<br class="gmail_msg"></p></blockquote></blockquote></div></div></div><div class="gmail_msg"><div style="font-family:sans-serif" class="gmail_msg"><div style="white-space:normal" class="gmail_msg"><blockquote style="border-left:2px solid #777;color:#777;margin:0 0 5px;padding-left:5px" class="gmail_msg"><blockquote style="border-left:2px solid #777;color:#999;margin:0 0 5px;padding-left:5px;border-left-color:#999" class="gmail_msg"><p dir="auto" class="gmail_msg">
- protocol Codable: Adopted by types to opt into archival. Conformance</p></blockquote></blockquote></div></div></div><div class="gmail_msg"><div style="font-family:sans-serif" class="gmail_msg"><div style="white-space:normal" class="gmail_msg"><blockquote style="border-left:2px solid #777;color:#777;margin:0 0 5px;padding-left:5px" class="gmail_msg"><blockquote style="border-left:2px solid #777;color:#999;margin:0 0 5px;padding-left:5px;border-left-color:#999" class="gmail_msg"><p dir="auto" class="gmail_msg"><br class="gmail_msg">
may be automatically derived in cases where all properties are also<br class="gmail_msg">
Codable.<br class="gmail_msg"></p></blockquote></blockquote></div></div></div><div class="gmail_msg"><div style="font-family:sans-serif" class="gmail_msg"><div style="white-space:normal" class="gmail_msg"><blockquote style="border-left:2px solid #777;color:#777;margin:0 0 5px;padding-left:5px" class="gmail_msg"><blockquote style="border-left:2px solid #777;color:#999;margin:0 0 5px;padding-left:5px;border-left-color:#999" class="gmail_msg"><p dir="auto" class="gmail_msg">
- protocol CodingKey: Adopted by types used as keys for keyed</p></blockquote></blockquote></div></div></div><div class="gmail_msg"><div style="font-family:sans-serif" class="gmail_msg"><div style="white-space:normal" class="gmail_msg"><blockquote style="border-left:2px solid #777;color:#777;margin:0 0 5px;padding-left:5px" class="gmail_msg"><blockquote style="border-left:2px solid #777;color:#999;margin:0 0 5px;padding-left:5px;border-left-color:#999" class="gmail_msg"><p dir="auto" class="gmail_msg"><br class="gmail_msg">
containers, replacing String keys with semantic types. Conformance may<br class="gmail_msg">
be automatically derived in most cases.<br class="gmail_msg"></p></blockquote></blockquote></div></div></div><div class="gmail_msg"><div style="font-family:sans-serif" class="gmail_msg"><div style="white-space:normal" class="gmail_msg"><blockquote style="border-left:2px solid #777;color:#777;margin:0 0 5px;padding-left:5px" class="gmail_msg"><blockquote style="border-left:2px solid #777;color:#999;margin:0 0 5px;padding-left:5px;border-left-color:#999" class="gmail_msg"><p dir="auto" class="gmail_msg">
- protocol Encoder: Adopted by types which can take Codable values and</p></blockquote></blockquote></div></div></div><div class="gmail_msg"><div style="font-family:sans-serif" class="gmail_msg"><div style="white-space:normal" class="gmail_msg"><blockquote style="border-left:2px solid #777;color:#777;margin:0 0 5px;padding-left:5px" class="gmail_msg"><blockquote style="border-left:2px solid #777;color:#999;margin:0 0 5px;padding-left:5px;border-left-color:#999" class="gmail_msg"><p dir="auto" class="gmail_msg"><br class="gmail_msg">
encode them into a native format.<br class="gmail_msg"></p></blockquote></blockquote></div></div></div><div class="gmail_msg"><div style="font-family:sans-serif" class="gmail_msg"><div style="white-space:normal" class="gmail_msg"><blockquote style="border-left:2px solid #777;color:#777;margin:0 0 5px;padding-left:5px" class="gmail_msg"><blockquote style="border-left:2px solid #777;color:#999;margin:0 0 5px;padding-left:5px;border-left-color:#999" class="gmail_msg"><p dir="auto" class="gmail_msg">
- class KeyedEncodingContainer<Key : CodingKey>: Subclasses of this</p></blockquote></blockquote></div></div></div><div class="gmail_msg"><div style="font-family:sans-serif" class="gmail_msg"><div style="white-space:normal" class="gmail_msg"><blockquote style="border-left:2px solid #777;color:#777;margin:0 0 5px;padding-left:5px" class="gmail_msg"><blockquote style="border-left:2px solid #777;color:#999;margin:0 0 5px;padding-left:5px;border-left-color:#999" class="gmail_msg"><p dir="auto" class="gmail_msg"><br class="gmail_msg">
type provide a concrete way to store encoded values by CodingKey.<br class="gmail_msg">
Types adopting Encoder should provide subclasses of<br class="gmail_msg">
KeyedEncodingContainer to vend.<br class="gmail_msg"></p></blockquote></blockquote></div></div></div><div class="gmail_msg"><div style="font-family:sans-serif" class="gmail_msg"><div style="white-space:normal" class="gmail_msg"><blockquote style="border-left:2px solid #777;color:#777;margin:0 0 5px;padding-left:5px" class="gmail_msg"><blockquote style="border-left:2px solid #777;color:#999;margin:0 0 5px;padding-left:5px;border-left-color:#999" class="gmail_msg"><p dir="auto" class="gmail_msg">
- protocol SingleValueEncodingContainer: Adopted by types which</p></blockquote></blockquote></div></div></div><div class="gmail_msg"><div style="font-family:sans-serif" class="gmail_msg"><div style="white-space:normal" class="gmail_msg"><blockquote style="border-left:2px solid #777;color:#777;margin:0 0 5px;padding-left:5px" class="gmail_msg"><blockquote style="border-left:2px solid #777;color:#999;margin:0 0 5px;padding-left:5px;border-left-color:#999" class="gmail_msg"><p dir="auto" class="gmail_msg"><br class="gmail_msg">
provide a concrete way to store a single encoded value. Types adopting<br class="gmail_msg">
Encoder should provide types conforming to<br class="gmail_msg">
SingleValueEncodingContainer to vend (but in many cases will be<br class="gmail_msg">
able to conform to it themselves).<br class="gmail_msg"></p></blockquote></blockquote></div></div></div><div class="gmail_msg"><div style="font-family:sans-serif" class="gmail_msg"><div style="white-space:normal" class="gmail_msg"><blockquote style="border-left:2px solid #777;color:#777;margin:0 0 5px;padding-left:5px" class="gmail_msg"><blockquote style="border-left:2px solid #777;color:#999;margin:0 0 5px;padding-left:5px;border-left-color:#999" class="gmail_msg"><p dir="auto" class="gmail_msg">
- protocol Decoder: Adopted by types which can take payloads in a</p></blockquote></blockquote></div></div></div><div class="gmail_msg"><div style="font-family:sans-serif" class="gmail_msg"><div style="white-space:normal" class="gmail_msg"><blockquote style="border-left:2px solid #777;color:#777;margin:0 0 5px;padding-left:5px" class="gmail_msg"><blockquote style="border-left:2px solid #777;color:#999;margin:0 0 5px;padding-left:5px;border-left-color:#999" class="gmail_msg"><p dir="auto" class="gmail_msg"><br class="gmail_msg">
native format and decode Codable values out of them.<br class="gmail_msg"></p></blockquote></blockquote></div></div></div><div class="gmail_msg"><div style="font-family:sans-serif" class="gmail_msg"><div style="white-space:normal" class="gmail_msg"><blockquote style="border-left:2px solid #777;color:#777;margin:0 0 5px;padding-left:5px" class="gmail_msg"><blockquote style="border-left:2px solid #777;color:#999;margin:0 0 5px;padding-left:5px;border-left-color:#999" class="gmail_msg"><p dir="auto" class="gmail_msg">
- class KeyedDecodingContainer<Key : CodingKey>: Subclasses of this</p></blockquote></blockquote></div></div></div><div class="gmail_msg"><div style="font-family:sans-serif" class="gmail_msg"><div style="white-space:normal" class="gmail_msg"><blockquote style="border-left:2px solid #777;color:#777;margin:0 0 5px;padding-left:5px" class="gmail_msg"><blockquote style="border-left:2px solid #777;color:#999;margin:0 0 5px;padding-left:5px;border-left-color:#999" class="gmail_msg"><p dir="auto" class="gmail_msg"><br class="gmail_msg">
type provide a concrete way to retrieve encoded values from storage by<br class="gmail_msg">
CodingKey. Types adopting Decoder should provide subclasses of<br class="gmail_msg">
KeyedDecodingContainer to vend.<br class="gmail_msg"></p></blockquote></blockquote></div></div></div><div class="gmail_msg"><div style="font-family:sans-serif" class="gmail_msg"><div style="white-space:normal" class="gmail_msg"><blockquote style="border-left:2px solid #777;color:#777;margin:0 0 5px;padding-left:5px" class="gmail_msg"><blockquote style="border-left:2px solid #777;color:#999;margin:0 0 5px;padding-left:5px;border-left-color:#999" class="gmail_msg"><p dir="auto" class="gmail_msg">
- protocol SingleValueDecodingContainer: Adopted by types which</p></blockquote></blockquote></div></div></div><div class="gmail_msg"><div style="font-family:sans-serif" class="gmail_msg"><div style="white-space:normal" class="gmail_msg"><blockquote style="border-left:2px solid #777;color:#777;margin:0 0 5px;padding-left:5px" class="gmail_msg"><blockquote style="border-left:2px solid #777;color:#999;margin:0 0 5px;padding-left:5px;border-left-color:#999" class="gmail_msg"><p dir="auto" class="gmail_msg"><br class="gmail_msg">
provide a concrete way to retrieve a single encoded value from storage.<br class="gmail_msg">
Types adopting Decoder should provide types conforming to<br class="gmail_msg">
SingleValueDecodingContainer to vend (but in many cases will be<br class="gmail_msg">
able to conform to it themselves).<br class="gmail_msg">
<br class="gmail_msg">
For end users of this API, adoption will primarily involve the Codable<br class="gmail_msg">
and CodingKey protocols. In order to participate in this new archival<br class="gmail_msg">
system, developers must add Codable conformance to their types:<br class="gmail_msg">
<br class="gmail_msg">
// If all properties are Codable, implementation is automatically derived:public struct Location : Codable {<br class="gmail_msg">
public let latitude: Double<br class="gmail_msg">
public let longitude: Double}<br class="gmail_msg">
public enum Animal : Int, Codable {<br class="gmail_msg">
case chicken = 1<br class="gmail_msg">
case dog<br class="gmail_msg">
case turkey<br class="gmail_msg">
case cow}<br class="gmail_msg">
public struct Farm : Codable {<br class="gmail_msg">
public let name: String<br class="gmail_msg">
public let location: Location<br class="gmail_msg">
public let animals: [Animal]}<br class="gmail_msg">
<br class="gmail_msg">
With developer participation, we will offer encoders and decoders<br class="gmail_msg">
(described in SE-NNNN, not here) that take advantage of this conformance to<br class="gmail_msg">
offer type-safe serialization of user models:<br class="gmail_msg">
<br class="gmail_msg">
let farm = Farm(name: "Old MacDonald's Farm",<br class="gmail_msg">
location: Location(latitude: 51.621648, longitude: 0.269273),<br class="gmail_msg"></p></blockquote></blockquote></div></div></div><div class="gmail_msg"><div style="font-family:sans-serif" class="gmail_msg"><div style="white-space:normal" class="gmail_msg"><blockquote style="border-left:2px solid #777;color:#777;margin:0 0 5px;padding-left:5px" class="gmail_msg"><blockquote style="border-left:2px solid #777;color:#999;margin:0 0 5px;padding-left:5px;border-left-color:#999" class="gmail_msg"><p dir="auto" class="gmail_msg">
animals: [.chicken, .dog, .cow, .turkey, .dog, .chicken, .cow, .turkey, .dog])let payload: Data = try JSONEncoder().encode(farm)</p></blockquote></blockquote></div></div></div><div class="gmail_msg"><div style="font-family:sans-serif" class="gmail_msg"><div style="white-space:normal" class="gmail_msg"><blockquote style="border-left:2px solid #777;color:#777;margin:0 0 5px;padding-left:5px" class="gmail_msg"><blockquote style="border-left:2px solid #777;color:#999;margin:0 0 5px;padding-left:5px;border-left-color:#999" class="gmail_msg"><p dir="auto" class="gmail_msg"><br class="gmail_msg">
do {<br class="gmail_msg">
let farm = try JSONDecoder().decode(Farm.self, from: payload)<br class="gmail_msg">
<br class="gmail_msg">
// Extracted as user types:<br class="gmail_msg">
let coordinates = "\(farm.location.latitude, farm.location.longitude)"} catch {<br class="gmail_msg">
// Encountered error during deserialization}<br class="gmail_msg">
<br class="gmail_msg">
This gives developers access to their data in a type-safe manner and a<br class="gmail_msg">
recognizable interface.<br class="gmail_msg">
Detailed design<br class="gmail_msg">
<br class="gmail_msg">
To support user types, we expose the Codable protocol:<br class="gmail_msg">
<br class="gmail_msg"></p></blockquote></blockquote></div></div></div><div class="gmail_msg"><div style="font-family:sans-serif" class="gmail_msg"><div style="white-space:normal" class="gmail_msg"><blockquote style="border-left:2px solid #777;color:#777;margin:0 0 5px;padding-left:5px" class="gmail_msg"><blockquote style="border-left:2px solid #777;color:#999;margin:0 0 5px;padding-left:5px;border-left-color:#999" class="gmail_msg"><p dir="auto" class="gmail_msg">
/// Conformance to `Codable` indicates that a type can marshal itself into and out of an external representation.public protocol Codable {</p></blockquote></blockquote></div></div></div><div class="gmail_msg"><div style="font-family:sans-serif" class="gmail_msg"><div style="white-space:normal" class="gmail_msg"><blockquote style="border-left:2px solid #777;color:#777;margin:0 0 5px;padding-left:5px" class="gmail_msg"><blockquote style="border-left:2px solid #777;color:#999;margin:0 0 5px;padding-left:5px;border-left-color:#999" class="gmail_msg"><p dir="auto" class="gmail_msg"><br class="gmail_msg">
/// Initializes `self` by decoding from `decoder`.<br class="gmail_msg">
///<br class="gmail_msg">
/// - parameter decoder: The decoder to read data from.<br class="gmail_msg">
/// - throws: An error if reading from the decoder fails, or if read data is corrupted or otherwise invalid.<br class="gmail_msg">
init(from decoder: Decoder) throws<br class="gmail_msg">
<br class="gmail_msg">
/// Encodes `self` into the given encoder.<br class="gmail_msg">
///<br class="gmail_msg">
/// If `self` fails to encode anything, `encoder` will encode an empty `.default` container in its place.<br class="gmail_msg">
///<br class="gmail_msg">
/// - parameter encoder: The encoder to write data to.<br class="gmail_msg">
/// - throws: An error if any values are invalid for `encoder`'s format.<br class="gmail_msg">
func encode(to encoder: Encoder) throws}<br class="gmail_msg">
<br class="gmail_msg">
By adopting Codable, user types opt in to this archival system.<br class="gmail_msg">
<br class="gmail_msg">
Structured types (i.e. types which encode as a collection of properties)<br class="gmail_msg">
encode and decode their properties in a keyed manner. Keys may be String-convertible<br class="gmail_msg">
or Int-convertible (or both), and user types which have properties should<br class="gmail_msg">
declare semantic key enums which map keys to their properties. Keys must<br class="gmail_msg">
conform to the CodingKey protocol:<br class="gmail_msg">
<br class="gmail_msg"></p></blockquote></blockquote></div></div></div><div class="gmail_msg"><div style="font-family:sans-serif" class="gmail_msg"><div style="white-space:normal" class="gmail_msg"><blockquote style="border-left:2px solid #777;color:#777;margin:0 0 5px;padding-left:5px" class="gmail_msg"><blockquote style="border-left:2px solid #777;color:#999;margin:0 0 5px;padding-left:5px;border-left-color:#999" class="gmail_msg"><p dir="auto" class="gmail_msg">
/// Conformance to `CodingKey` indicates that a type can be used as a key for encoding and decoding.public protocol CodingKey {</p></blockquote></blockquote></div></div></div><div class="gmail_msg"><div style="font-family:sans-serif" class="gmail_msg"><div style="white-space:normal" class="gmail_msg"><blockquote style="border-left:2px solid #777;color:#777;margin:0 0 5px;padding-left:5px" class="gmail_msg"><blockquote style="border-left:2px solid #777;color:#999;margin:0 0 5px;padding-left:5px;border-left-color:#999" class="gmail_msg"><p dir="auto" class="gmail_msg"><br class="gmail_msg">
/// The string to use in a named collection (e.g. a string-keyed dictionary).<br class="gmail_msg">
var stringValue: String? { get }<br class="gmail_msg">
<br class="gmail_msg">
/// Initializes `self` from a string.<br class="gmail_msg">
///<br class="gmail_msg">
/// - parameter stringValue: The string value of the desired key.<br class="gmail_msg">
/// - returns: An instance of `Self` from the given string, or `nil` if the given string does not correspond to any instance of `Self`.<br class="gmail_msg">
init?(stringValue: String)<br class="gmail_msg">
<br class="gmail_msg">
/// The int to use in an indexed collection (e.g. an int-keyed dictionary).<br class="gmail_msg">
var intValue: Int? { get }<br class="gmail_msg">
<br class="gmail_msg">
/// Initializes `self` from an integer.<br class="gmail_msg">
///<br class="gmail_msg">
/// - parameter intValue: The integer value of the desired key.<br class="gmail_msg">
/// - returns: An instance of `Self` from the given integer, or `nil` if the given integer does not correspond to any instance of `Self`.<br class="gmail_msg">
init?(intValue: Int)}<br class="gmail_msg">
<br class="gmail_msg">
For most types, String-convertible keys are a reasonable default; for<br class="gmail_msg">
performance, however, Int-convertible keys are preferred, and Encoders may<br class="gmail_msg">
choose to make use of Ints over Strings. Framework types should provide<br class="gmail_msg">
keys which have both for flexibility and performance across different types<br class="gmail_msg">
of Encoders. It is generally an error to provide a key which has neither<br class="gmail_msg">
a stringValue nor an intValue.<br class="gmail_msg">
<br class="gmail_msg">
By default, CodingKey conformance can be derived for enums which have<br class="gmail_msg">
either String or Int backing:<br class="gmail_msg">
<br class="gmail_msg">
enum Keys1 : CodingKey {<br class="gmail_msg">
case a // (stringValue: "a", intValue: nil)<br class="gmail_msg">
case b // (stringValue: "b", intValue: nil)}<br class="gmail_msg">
enum Keys2 : String, CodingKey {<br class="gmail_msg">
case c = "foo" // (stringValue: "foo", intValue: nil)<br class="gmail_msg">
case d // (stringValue: "d", intValue: nil)}<br class="gmail_msg">
enum Keys3 : Int, CodingKey {<br class="gmail_msg">
case e = 4 // (stringValue: "e", intValue: 4)<br class="gmail_msg">
case f // (stringValue: "f", intValue: 5)<br class="gmail_msg">
case g = 9 // (stringValue: "g", intValue: 9)}<br class="gmail_msg">
<br class="gmail_msg">
Coding keys which are not enums, have associated values, or have other<br class="gmail_msg">
raw representations must implement these methods manually.<br class="gmail_msg">
<br class="gmail_msg">
In addition to automatic CodingKey conformance derivation for enums,<br class="gmail_msg">
Codableconformance can be automatically derived for certain types as well:<br class="gmail_msg">
<br class="gmail_msg"></p></blockquote></blockquote></div></div></div><div class="gmail_msg"><div style="font-family:sans-serif" class="gmail_msg"><div style="white-space:normal" class="gmail_msg"><blockquote style="border-left:2px solid #777;color:#777;margin:0 0 5px;padding-left:5px" class="gmail_msg"><blockquote style="border-left:2px solid #777;color:#999;margin:0 0 5px;padding-left:5px;border-left-color:#999" class="gmail_msg"><p dir="auto" class="gmail_msg">
1. Types whose properties are all either Codable or primitive get an</p></blockquote></blockquote></div></div></div><div class="gmail_msg"><div style="font-family:sans-serif" class="gmail_msg"><div style="white-space:normal" class="gmail_msg"><blockquote style="border-left:2px solid #777;color:#777;margin:0 0 5px;padding-left:5px" class="gmail_msg"><blockquote style="border-left:2px solid #777;color:#999;margin:0 0 5px;padding-left:5px;border-left-color:#999" class="gmail_msg"><p dir="auto" class="gmail_msg"><br class="gmail_msg">
automatically derived String-backed CodingKeys enum mapping properties<br class="gmail_msg">
to case names<br class="gmail_msg"></p></blockquote></blockquote></div></div></div><div class="gmail_msg"><div style="font-family:sans-serif" class="gmail_msg"><div style="white-space:normal" class="gmail_msg"><blockquote style="border-left:2px solid #777;color:#777;margin:0 0 5px;padding-left:5px" class="gmail_msg"><blockquote style="border-left:2px solid #777;color:#999;margin:0 0 5px;padding-left:5px;border-left-color:#999" class="gmail_msg"><p dir="auto" class="gmail_msg">
2. Types falling into (1) and types which provide a CodingKeys enum (directly</p></blockquote></blockquote></div></div></div><div class="gmail_msg"><div style="font-family:sans-serif" class="gmail_msg"><div style="white-space:normal" class="gmail_msg"><blockquote style="border-left:2px solid #777;color:#777;margin:0 0 5px;padding-left:5px" class="gmail_msg"><blockquote style="border-left:2px solid #777;color:#999;margin:0 0 5px;padding-left:5px;border-left-color:#999" class="gmail_msg"><p dir="auto" class="gmail_msg"><br class="gmail_msg">
or via a typealias) whose case names map to properties which are all<br class="gmail_msg">
Codableget automatic derivation of init(from:) and encode(to:) using<br class="gmail_msg">
those properties and keys. Types may choose to provide a custom<br class="gmail_msg">
init(from:) or encode(to:) (or both); whichever they do not provide<br class="gmail_msg">
will be automatically derived<br class="gmail_msg"></p></blockquote></blockquote></div></div></div><div class="gmail_msg"><div style="font-family:sans-serif" class="gmail_msg"><div style="white-space:normal" class="gmail_msg"><blockquote style="border-left:2px solid #777;color:#777;margin:0 0 5px;padding-left:5px" class="gmail_msg"><blockquote style="border-left:2px solid #777;color:#999;margin:0 0 5px;padding-left:5px;border-left-color:#999" class="gmail_msg"><p dir="auto" class="gmail_msg">
3. Types which fall into neither (1) nor (2) will have to provide a</p></blockquote></blockquote></div></div></div><div class="gmail_msg"><div style="font-family:sans-serif" class="gmail_msg"><div style="white-space:normal" class="gmail_msg"><blockquote style="border-left:2px solid #777;color:#777;margin:0 0 5px;padding-left:5px" class="gmail_msg"><blockquote style="border-left:2px solid #777;color:#999;margin:0 0 5px;padding-left:5px;border-left-color:#999" class="gmail_msg"><p dir="auto" class="gmail_msg"><br class="gmail_msg">
custom key type and provide their own init(from:) and encode(to:)<br class="gmail_msg">
<br class="gmail_msg">
Many types will either allow for automatic derivation of all codability<br class="gmail_msg">
(1), or provide a custom key subset and take advantage of automatic method<br class="gmail_msg">
derivation (2).<br class="gmail_msg">
Encoding and Decoding<br class="gmail_msg">
<br class="gmail_msg">
Types which are encodable encode their data into a container provided by<br class="gmail_msg">
their Encoder:<br class="gmail_msg">
<br class="gmail_msg"></p></blockquote></blockquote></div></div></div><div class="gmail_msg"><div style="font-family:sans-serif" class="gmail_msg"><div style="white-space:normal" class="gmail_msg"><blockquote style="border-left:2px solid #777;color:#777;margin:0 0 5px;padding-left:5px" class="gmail_msg"><blockquote style="border-left:2px solid #777;color:#999;margin:0 0 5px;padding-left:5px;border-left-color:#999" class="gmail_msg"><p dir="auto" class="gmail_msg">
/// An `Encoder` is a type which can encode values into a native format for external representation.public protocol Encoder {</p></blockquote></blockquote></div></div></div><div class="gmail_msg"><div style="font-family:sans-serif" class="gmail_msg"><div style="white-space:normal" class="gmail_msg"><blockquote style="border-left:2px solid #777;color:#777;margin:0 0 5px;padding-left:5px" class="gmail_msg"><blockquote style="border-left:2px solid #777;color:#999;margin:0 0 5px;padding-left:5px;border-left-color:#999" class="gmail_msg"><p dir="auto" class="gmail_msg"><br class="gmail_msg">
/// Populates `self` with an encoding container (of `.default` type) and returns it, keyed by the given key type.<br class="gmail_msg">
///<br class="gmail_msg">
/// - parameter type: The key type to use for the container.<br class="gmail_msg">
/// - returns: A new keyed encoding container.<br class="gmail_msg">
/// - precondition: May not be called after a previous `self.container(keyedBy:)` call of a different `EncodingContainerType`.<br class="gmail_msg">
/// - precondition: May not be called after a value has been encoded through a prior `self.singleValueContainer()` call.<br class="gmail_msg">
func container<Key : CodingKey>(keyedBy type: Key.Type) -> KeyedEncodingContainer<Key><br class="gmail_msg">
<br class="gmail_msg">
/// Returns an encoding container appropriate for holding a single primitive value.<br class="gmail_msg">
///<br class="gmail_msg">
/// - returns: A new empty single value container.<br class="gmail_msg">
/// - precondition: May not be called after a prior `self.container(keyedBy:)` call.<br class="gmail_msg">
/// - precondition: May not be called after a value has been encoded through a previous `self.singleValueContainer()` call.<br class="gmail_msg">
func singleValueContainer() -> SingleValueEncodingContainer<br class="gmail_msg">
<br class="gmail_msg">
/// The path of coding keys taken to get to this point in encoding.<br class="gmail_msg">
var codingKeyContext: [CodingKey] { get }}<br class="gmail_msg"></p></blockquote></blockquote></div></div></div><div class="gmail_msg"><div style="font-family:sans-serif" class="gmail_msg"><div style="white-space:normal" class="gmail_msg"><blockquote style="border-left:2px solid #777;color:#777;margin:0 0 5px;padding-left:5px" class="gmail_msg"><blockquote style="border-left:2px solid #777;color:#999;margin:0 0 5px;padding-left:5px;border-left-color:#999" class="gmail_msg"><p dir="auto" class="gmail_msg">
// Continuing examples from before; below is automatically generated by the compiler if no customization is needed.public struct Location : Codable {</p></blockquote></blockquote></div></div></div><div class="gmail_msg"><div style="font-family:sans-serif" class="gmail_msg"><div style="white-space:normal" class="gmail_msg"><blockquote style="border-left:2px solid #777;color:#777;margin:0 0 5px;padding-left:5px" class="gmail_msg"><blockquote style="border-left:2px solid #777;color:#999;margin:0 0 5px;padding-left:5px;border-left-color:#999" class="gmail_msg"><p dir="auto" class="gmail_msg"><br class="gmail_msg">
private enum CodingKeys : CodingKey {<br class="gmail_msg">
case latitutude<br class="gmail_msg">
case longitude<br class="gmail_msg">
}<br class="gmail_msg">
<br class="gmail_msg">
public func encode(to encoder: Encoder) throws {<br class="gmail_msg">
// Generic keyed encoder gives type-safe key access: cannot encode with keys of the wrong type.<br class="gmail_msg">
let container = encoder.container(keyedBy: CodingKeys.self)<br class="gmail_msg">
<br class="gmail_msg">
// The encoder is generic on the key -- free key autocompletion here.<br class="gmail_msg">
try container.encode(latitude, forKey: .latitude)<br class="gmail_msg">
try container.encode(longitude, forKey: .longitude)<br class="gmail_msg">
}}<br class="gmail_msg">
public struct Farm : Codable {<br class="gmail_msg">
private enum CodingKeys : CodingKey {<br class="gmail_msg">
case name<br class="gmail_msg">
case location<br class="gmail_msg">
case animals<br class="gmail_msg">
}<br class="gmail_msg">
<br class="gmail_msg">
public func encode(to encoder: Encoder) throws {<br class="gmail_msg">
let container = encoder.container(keyedBy: CodingKeys.self)<br class="gmail_msg">
try container.encode(name<br class="gmail_msg">
<br class="gmail_msg">
</p></blockquote></blockquote></div></div></div></blockquote></div></div></div></div>