<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=""><div><div class=""><div class="">Hello Itai,</div><div class=""><br class=""></div><div class="">Thanks for helping sorting things out.</div><div class=""><br class=""></div><div class="">I have since my initial question a better understanding of Codable, and I hope I can better express the trouble. I bump against the fact that SE-0166 and SE-0167 assume that there is a single kind of coding keys.</div><div class=""><br class=""></div><div class="">This is the case for JSON and Plist:</div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span></div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>{</div><div class=""><span class="Apple-tab-span" style="white-space:pre">                </span>"a": "foo"</div><div class=""><span class="Apple-tab-span" style="white-space:pre">                </span>"b": { ... }</div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>}</div><div class=""><br class=""></div><div class="">But imagine a different serialization format where we don't use the same kind of keys for values and objects. Values are stored on red keys, and objects on blue keys:</div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span></div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>{</div><div class=""><span class="Apple-tab-span" style="white-space:pre">                </span>"a" (red): "foo"</div><div class=""><span class="Apple-tab-span" style="white-space:pre">                </span>"b" (blue): { ... }</div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>}</div><div class=""><br class=""></div><div class="">This serialization format accepts keys with the same name, as long as they don't have the same color:</div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span></div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>{</div><div class=""><span class="Apple-tab-span" style="white-space:pre">                </span>"a" (red): "foo"</div><div class=""><span class="Apple-tab-span" style="white-space:pre">                </span>"a" (blue): { ... }</div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>}</div><div class=""><br class=""></div><div class="">This format is used by SQL rows in GRDB. A SQL row is both a set of columns with associated values (the "red" keys), plus a set of scopes with associated "view" on the row (the blue keys):</div><div class=""><br class=""></div><div class=""><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><div style="margin: 0px; line-height: normal;" class=""><span style="font-variant-ligatures: no-common-ligatures" class="">&nbsp; &nbsp;&nbsp;</span><span style="font-variant-ligatures: no-common-ligatures; color: #ba2da2" class="">let</span><span style="font-variant-ligatures: no-common-ligatures" class=""> row = </span><span style="font-variant-ligatures: no-common-ligatures; color: #3e1e81" class="">...</span></div><div style="margin: 0px; line-height: normal;" class=""><span style="font-variant-ligatures: no-common-ligatures" class="">&nbsp; &nbsp; row[</span><span style="font-variant-ligatures: no-common-ligatures; color: #d12f1b" class="">"id"</span><span style="font-variant-ligatures: no-common-ligatures" class="">]&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="font-variant-ligatures: no-common-ligatures; color: #008400" class="">// 1</span></div><div style="margin: 0px; line-height: normal;" class=""><span style="font-variant-ligatures: no-common-ligatures" class="">&nbsp; &nbsp; </span><span style="font-variant-ligatures: no-common-ligatures; color: #ba2da2" class="">let</span><span style="font-variant-ligatures: no-common-ligatures" class=""> scopedRpw = </span><span style="font-variant-ligatures: no-common-ligatures; color: #4f8187" class="">row</span><span style="font-variant-ligatures: no-common-ligatures" class="">.scoped(on: </span><span style="font-variant-ligatures: no-common-ligatures; color: #d12f1b" class="">"foo"</span><span style="font-variant-ligatures: no-common-ligatures" class="">)! </span><span style="font-variant-ligatures: no-common-ligatures; color: #008400" class="">// &lt;Row "id":2, "foo": "bar"&gt;</span></div><div style="margin: 0px; line-height: normal;" class=""><span style="font-variant-ligatures: no-common-ligatures" class="">&nbsp; &nbsp; scopedRow[</span><span style="font-variant-ligatures: no-common-ligatures; color: #d12f1b" class="">"id"</span><span style="font-variant-ligatures: no-common-ligatures" class="">]&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="font-variant-ligatures: no-common-ligatures; color: #008400" class="">// 2</span></div><div class=""><span style="font-variant-ligatures: no-common-ligatures; color: #008400" class=""><br class=""></span></div></div></div><div class="">If you wonder: "but why???": columns and scopes are what can make rows a suitable base for hierarchical decoding, just like JSON and PList. When a flat SQL row fetched from a joined query is seen as a hierarchical structure, several simple `init(row:)` initializers can get the rows they expect, and we load a complex graph of objects. I have high hopes (<a href="https://github.com/groue/GRDB.swift/issues/176#issuecomment-285938568" class="">https://github.com/groue/GRDB.swift/issues/176#issuecomment-285938568</a>).</div><div class=""><br class=""></div><div class="">I care about Codable because of the code generation is has been blessed with. I expect GRDB users to rush on Codable since they won't have any longer to write the decoding boilerplate.</div></div><div class=""><br class=""></div><div class=""><br class=""></div></div><div class=""><blockquote type="cite" class=""><div class=""><div class="" style="font-family: sans-serif;"><div class=""></div></div></div></blockquote><div><blockquote type="cite" class=""><div class=""><span style="font-family: sans-serif;" class="">I have to confess that I’m not familiar with this concept, but let’s take a look:</span></div><div class=""><div class=""><div style="font-family:sans-serif" class=""><div style="white-space:normal" class="">

<pre style="background-color: rgb(247, 247, 247); border-top-left-radius: 5px; border-top-right-radius: 5px; border-bottom-right-radius: 5px; border-bottom-left-radius: 5px; margin-left: 15px; margin-right: 15px; max-width: 90vw; overflow-x: auto; padding: 5px;" bgcolor="#F7F7F7" class=""><code style="background-color:#F7F7F7; border-radius:3px; margin:0; padding:0" bgcolor="#F7F7F7" class=""><span style="color: #008800; font-weight: bold" class="">if</span> <span style="color: #008800; font-weight: bold" class="">let</span> <span style="color: #996633" class="">valueType</span> = T.<span style="color: #008800; font-weight: bold" class="">self</span> <span style="color: #008800; font-weight: bold" class="">as</span>? DatabaseValueConvertible.<span style="color: #008800; font-weight: bold" class="">Type</span> {
    <span style="color: #888888" class="">// if column is missing, trigger the "missing key" error or return nil.</span>
} <span style="color: #008800; font-weight: bold" class="">else</span> <span style="color: #008800; font-weight: bold" class="">if</span> <span style="color: #008800; font-weight: bold" class="">let</span> <span style="color: #996633" class="">complexType</span> = T.<span style="color: #008800; font-weight: bold" class="">self</span> <span style="color: #008800; font-weight: bold" class="">as</span>? RowConvertible.<span style="color: #008800; font-weight: bold" class="">Type</span> {
    <span style="color: #888888" class="">// if row scope is missing, trigger the "missing key" error or return nil.</span>
} <span style="color: #008800; font-weight: bold" class="">else</span> {
    <span style="color: #888888" class="">// don't know what to do</span>
    <span style="color: #007020" class="">fatalError</span>(<span style="background-color: #fff0f0" class="">"unsupported"</span>)
}
</code></pre><p dir="auto" class="">Is it appropriate for a type which is neither <code style="background-color:#F7F7F7; border-radius:3px; margin:0; padding:0 0.4em" bgcolor="#F7F7F7" class="">DatabaseValueConvertible</code> nor <code style="background-color:#F7F7F7; border-radius:3px; margin:0; padding:0 0.4em" bgcolor="#F7F7F7" class="">RowConvertible</code> to be decoded with your decoder? If not, then this warrants a <code style="background-color:#F7F7F7; border-radius:3px; margin:0; padding:0 0.4em" bgcolor="#F7F7F7" class="">preconditionFailure</code> or an error of some sort, right? In this case, that would be valid.</p></div></div></div></div></blockquote><div><div><div><div>Yes it is, there's no point preventing this.</div><div><br class=""></div><div>We can forget the GRDB DatabaseValueConvertible and RowConvertible protocals in this discussion - they have their purpose, but are irrelevant here, and I was wrong letting them in the discussion. Will you look at some updated code?</div><div><br class=""></div><div>In practice, let's consider the `KeyedDecodingContainerProtocol.decode(_:forKey:)` method. The decoding container is asked for a type T. It does not know yet if T is a single-value or a keyed type. No problem: it delays the decision until the Decoder is asked for a container:</div><div>&nbsp; &nbsp;&nbsp;</div><div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures" class="">&nbsp; &nbsp;&nbsp;</span><span style="font-variant-ligatures: no-common-ligatures; color: #ba2da2" class="">struct</span><span style="font-variant-ligatures: no-common-ligatures" class=""> RowKeyedDecodingContainer&lt;Key: </span><span style="font-variant-ligatures: no-common-ligatures; color: #703daa" class="">CodingKey</span><span style="font-variant-ligatures: no-common-ligatures" class="">&gt;: </span><span style="font-variant-ligatures: no-common-ligatures; color: #703daa" class="">KeyedDecodingContainerProtocol</span><span style="font-variant-ligatures: no-common-ligatures" class=""> {</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures" class="">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="font-variant-ligatures: no-common-ligatures; color: #ba2da2" class="">func</span><span style="font-variant-ligatures: no-common-ligatures" class=""> decode&lt;T&gt;(</span><span style="font-variant-ligatures: no-common-ligatures; color: #ba2da2" class="">_</span><span style="font-variant-ligatures: no-common-ligatures" class=""> type: T.Type, forKey key: Key) </span><span style="font-variant-ligatures: no-common-ligatures; color: #ba2da2" class="">throws</span><span style="font-variant-ligatures: no-common-ligatures" class=""> -&gt; T </span><span style="font-variant-ligatures: no-common-ligatures; color: #ba2da2" class="">where</span><span style="font-variant-ligatures: no-common-ligatures" class=""> </span><span style="font-variant-ligatures: no-common-ligatures; color: #703daa" class="">T</span><span style="font-variant-ligatures: no-common-ligatures" class=""> : </span><span style="font-variant-ligatures: no-common-ligatures; color: #703daa" class="">Decodable</span><span style="font-variant-ligatures: no-common-ligatures" class=""> {</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(0, 132, 0);" class=""><span style="font-variant-ligatures: no-common-ligatures; color: #000000" class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="font-variant-ligatures: no-common-ligatures" class="">// Push the key, and wait until the decoder is asked for a container</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(0, 132, 0);" class=""><span style="font-variant-ligatures: no-common-ligatures; color: #000000" class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="font-variant-ligatures: no-common-ligatures" class="">// so that we know if T is keyed, or single-value:</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures" class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="font-variant-ligatures: no-common-ligatures; color: #ba2da2" class="">return</span><span style="font-variant-ligatures: no-common-ligatures" class=""> </span><span style="font-variant-ligatures: no-common-ligatures; color: #ba2da2" class="">try</span><span style="font-variant-ligatures: no-common-ligatures" class=""> </span><span style="font-variant-ligatures: no-common-ligatures; color: #703daa" class="">T</span><span style="font-variant-ligatures: no-common-ligatures" class="">(from: RowDecoder(row: row, codingPath: codingPath + [key]))</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures" class="">&nbsp; &nbsp; &nbsp; &nbsp; }</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures" class="">&nbsp; &nbsp; }</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; min-height: 13px;" class=""><span style="font-variant-ligatures: no-common-ligatures" class=""></span><br class=""></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures" class="">&nbsp; &nbsp; </span><span style="font-variant-ligatures: no-common-ligatures; color: #ba2da2" class="">struct</span><span style="font-variant-ligatures: no-common-ligatures" class=""> RowDecoder: </span><span style="font-variant-ligatures: no-common-ligatures; color: #703daa" class="">Decoder</span><span style="font-variant-ligatures: no-common-ligatures" class=""> {</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures" class="">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="font-variant-ligatures: no-common-ligatures; color: #ba2da2" class="">func</span><span style="font-variant-ligatures: no-common-ligatures" class=""> container&lt;Key&gt;(keyedBy type: </span><span style="font-variant-ligatures: no-common-ligatures; color: #703daa" class="">Key</span><span style="font-variant-ligatures: no-common-ligatures" class="">.Type) </span><span style="font-variant-ligatures: no-common-ligatures; color: #ba2da2" class="">throws</span><span style="font-variant-ligatures: no-common-ligatures" class=""> -&gt; </span><span style="font-variant-ligatures: no-common-ligatures; color: #703daa" class="">KeyedDecodingContainer</span><span style="font-variant-ligatures: no-common-ligatures" class="">&lt;</span><span style="font-variant-ligatures: no-common-ligatures; color: #703daa" class="">Key</span><span style="font-variant-ligatures: no-common-ligatures" class="">&gt; {</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures" class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="font-variant-ligatures: no-common-ligatures; color: #ba2da2" class="">if</span><span style="font-variant-ligatures: no-common-ligatures" class=""> </span><span style="font-variant-ligatures: no-common-ligatures; color: #ba2da2" class="">let</span><span style="font-variant-ligatures: no-common-ligatures" class=""> key = codingPath.last {</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(0, 132, 0);" class=""><span style="font-variant-ligatures: no-common-ligatures; color: #000000" class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="font-variant-ligatures: no-common-ligatures" class="">// Asked for a keyed type: look for a row scope</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures" class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="font-variant-ligatures: no-common-ligatures; color: #ba2da2" class="">if</span><span style="font-variant-ligatures: no-common-ligatures" class=""> </span><span style="font-variant-ligatures: no-common-ligatures; color: #ba2da2" class="">let</span><span style="font-variant-ligatures: no-common-ligatures" class=""> scopedRow = row.scoped(on: key!.stringValue) {</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures" class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="font-variant-ligatures: no-common-ligatures; color: #ba2da2" class="">let</span><span style="font-variant-ligatures: no-common-ligatures" class=""> container = RowKeyedDecodingContainer&lt;</span><span style="font-variant-ligatures: no-common-ligatures; color: #703daa" class="">Key</span><span style="font-variant-ligatures: no-common-ligatures" class="">&gt;(row: scopedRow, codingPath: codingPath)</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures" class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="font-variant-ligatures: no-common-ligatures; color: #ba2da2" class="">return</span><span style="font-variant-ligatures: no-common-ligatures" class=""> KeyedDecodingContainer(container)</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures" class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } </span><span style="font-variant-ligatures: no-common-ligatures; color: #ba2da2" class="">else</span><span style="font-variant-ligatures: no-common-ligatures" class=""> {</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures" class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="font-variant-ligatures: no-common-ligatures; color: #ba2da2" class="">throw</span><span style="font-variant-ligatures: no-common-ligatures" class=""> DecodingError.keyNotFound...</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures" class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures" class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } </span><span style="font-variant-ligatures: no-common-ligatures; color: #ba2da2" class="">else</span><span style="font-variant-ligatures: no-common-ligatures" class=""> {</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(0, 132, 0);" class=""><span style="font-variant-ligatures: no-common-ligatures; color: #000000" class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="font-variant-ligatures: no-common-ligatures" class="">// Asked for a keyed type at the top level</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures" class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="font-variant-ligatures: no-common-ligatures; color: #ba2da2" class="">let</span><span style="font-variant-ligatures: no-common-ligatures" class=""> container = RowKeyedDecodingContainer&lt;</span><span style="font-variant-ligatures: no-common-ligatures; color: #703daa" class="">Key</span><span style="font-variant-ligatures: no-common-ligatures" class="">&gt;(row: row, codingPath: codingPath)</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures" class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="font-variant-ligatures: no-common-ligatures; color: #ba2da2" class="">return</span><span style="font-variant-ligatures: no-common-ligatures" class=""> KeyedDecodingContainer(container)</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures" class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures" class="">&nbsp; &nbsp; &nbsp; &nbsp; }</span></div><p style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; min-height: 13px;" class=""><span style="font-variant-ligatures: no-common-ligatures" class="">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;</span><br class="webkit-block-placeholder"></p><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures" class="">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="font-variant-ligatures: no-common-ligatures; color: #ba2da2" class="">func</span><span style="font-variant-ligatures: no-common-ligatures" class=""> singleValueContainer() </span><span style="font-variant-ligatures: no-common-ligatures; color: #ba2da2" class="">throws</span><span style="font-variant-ligatures: no-common-ligatures" class=""> -&gt; </span><span style="font-variant-ligatures: no-common-ligatures; color: #703daa" class="">SingleValueDecodingContainer</span><span style="font-variant-ligatures: no-common-ligatures" class=""> {</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(0, 132, 0);" class=""><span style="font-variant-ligatures: no-common-ligatures; color: #000000" class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="font-variant-ligatures: no-common-ligatures" class="">// Asked for a single-value type: look for a column</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures" class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="font-variant-ligatures: no-common-ligatures; color: #ba2da2" class="">return</span><span style="font-variant-ligatures: no-common-ligatures" class=""> RowColumnDecodingContainer(row: row, column: codingPath.last!!.stringValue)</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures" class="">&nbsp; &nbsp; &nbsp; &nbsp; }</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures" class="">&nbsp; &nbsp; }</span></div><div class=""><span style="font-variant-ligatures: no-common-ligatures" class=""><br class=""></span></div></div><div>(Sorry for the bangs, I still have to understand how I should deal with nil coding keys)</div><div><br class=""></div><div>This works pretty well so far.</div><div><br class=""></div><div>But now let's consider the `KeyedDecodingContainerProtocol.decodeIfPresent(_:forKey:)` method. Now we have a problem. This method must return nil if the key is missing. But which key? We don't know if the decoded type is keyed, or single-value. We can't postpone the decision, as above. So we have to double guess:</div><div><br class=""></div><div>My current implementation is the following:</div><div><br class=""></div><div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures" class="">&nbsp; &nbsp;&nbsp;</span><span style="font-variant-ligatures: no-common-ligatures; color: #ba2da2" class="">func</span><span style="font-variant-ligatures: no-common-ligatures" class=""> decodeIfPresent&lt;T&gt;(</span><span style="font-variant-ligatures: no-common-ligatures; color: #ba2da2" class="">_</span><span style="font-variant-ligatures: no-common-ligatures" class=""> type: </span><span style="font-variant-ligatures: no-common-ligatures; color: #4f8187" class="">T</span><span style="font-variant-ligatures: no-common-ligatures" class="">.Type, forKey key: Key) </span><span style="font-variant-ligatures: no-common-ligatures; color: #ba2da2" class="">throws</span><span style="font-variant-ligatures: no-common-ligatures" class=""> -&gt; </span><span style="font-variant-ligatures: no-common-ligatures; color: #4f8187" class="">T</span><span style="font-variant-ligatures: no-common-ligatures" class="">? </span><span style="font-variant-ligatures: no-common-ligatures; color: #ba2da2" class="">where</span><span style="font-variant-ligatures: no-common-ligatures" class=""> </span><span style="font-variant-ligatures: no-common-ligatures; color: #4f8187" class="">T</span><span style="font-variant-ligatures: no-common-ligatures" class=""> : </span><span style="font-variant-ligatures: no-common-ligatures; color: #703daa" class="">Decodable</span><span style="font-variant-ligatures: no-common-ligatures" class=""> {</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures" class="">&nbsp; &nbsp; &nbsp; &nbsp; </span><span style="font-variant-ligatures: no-common-ligatures; color: #ba2da2" class="">if</span><span style="font-variant-ligatures: no-common-ligatures" class=""> </span><span style="font-variant-ligatures: no-common-ligatures; color: #ba2da2" class="">let</span><span style="font-variant-ligatures: no-common-ligatures" class=""> dbValue: </span><span style="font-variant-ligatures: no-common-ligatures; color: #4f8187" class="">DatabaseValue</span><span style="font-variant-ligatures: no-common-ligatures" class=""> = row[key.stringValue] {</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(0, 132, 0);" class=""><span style="font-variant-ligatures: no-common-ligatures; color: #000000" class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="font-variant-ligatures: no-common-ligatures" class="">// We don't know if T(from: Decoder) will request a single value</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(0, 132, 0);" class=""><span style="font-variant-ligatures: no-common-ligatures; color: #000000" class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="font-variant-ligatures: no-common-ligatures" class="">// container, or a keyed container.</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures" class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="font-variant-ligatures: no-common-ligatures; color: #008400" class="">//</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(0, 132, 0);" class=""><span style="font-variant-ligatures: no-common-ligatures; color: #000000" class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="font-variant-ligatures: no-common-ligatures" class="">// Since the column is present, let's assume that T will ask for a</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(0, 132, 0);" class=""><span style="font-variant-ligatures: no-common-ligatures; color: #000000" class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="font-variant-ligatures: no-common-ligatures" class="">// single value container (a column). This is our only opportunity</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(0, 132, 0);" class=""><span style="font-variant-ligatures: no-common-ligatures; color: #000000" class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="font-variant-ligatures: no-common-ligatures" class="">// to turn NULL into nil. If T eventually asks for a keyed container</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(0, 132, 0);" class=""><span style="font-variant-ligatures: no-common-ligatures; color: #000000" class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="font-variant-ligatures: no-common-ligatures" class="">// (a row scope), then the user will face a weird error.</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures" class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="font-variant-ligatures: no-common-ligatures; color: #ba2da2" class="">if</span><span style="font-variant-ligatures: no-common-ligatures" class=""> dbValue.</span><span style="font-variant-ligatures: no-common-ligatures; color: #4f8187" class="">isNull</span><span style="font-variant-ligatures: no-common-ligatures" class=""> {</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures" class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="font-variant-ligatures: no-common-ligatures; color: #ba2da2" class="">return</span><span style="font-variant-ligatures: no-common-ligatures" class=""> </span><span style="font-variant-ligatures: no-common-ligatures; color: #ba2da2" class="">nil</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures" class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } </span><span style="font-variant-ligatures: no-common-ligatures; color: #ba2da2" class="">else</span><span style="font-variant-ligatures: no-common-ligatures" class=""> {</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures" class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="font-variant-ligatures: no-common-ligatures; color: #ba2da2" class="">return</span><span style="font-variant-ligatures: no-common-ligatures" class=""> </span><span style="font-variant-ligatures: no-common-ligatures; color: #ba2da2" class="">try</span><span style="font-variant-ligatures: no-common-ligatures" class=""> </span><span style="font-variant-ligatures: no-common-ligatures; color: #4f8187" class="">T</span><span style="font-variant-ligatures: no-common-ligatures" class="">(from: RowDecoder(row: row, codingPath: codingPath + [key]))</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures" class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures" class="">&nbsp; &nbsp; &nbsp; &nbsp; } </span><span style="font-variant-ligatures: no-common-ligatures; color: #ba2da2" class="">else</span><span style="font-variant-ligatures: no-common-ligatures" class=""> </span><span style="font-variant-ligatures: no-common-ligatures; color: #ba2da2" class="">if</span><span style="font-variant-ligatures: no-common-ligatures" class=""> row.scoped(on: key.stringValue) != </span><span style="font-variant-ligatures: no-common-ligatures; color: #ba2da2" class="">nil</span><span style="font-variant-ligatures: no-common-ligatures" class=""> {</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(0, 132, 0);" class=""><span style="font-variant-ligatures: no-common-ligatures; color: #000000" class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="font-variant-ligatures: no-common-ligatures" class="">// We don't know if T(from: Decoder) will request a single value</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(0, 132, 0);" class=""><span style="font-variant-ligatures: no-common-ligatures; color: #000000" class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="font-variant-ligatures: no-common-ligatures" class="">// container, or a keyed container.</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures" class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="font-variant-ligatures: no-common-ligatures; color: #008400" class="">//</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(0, 132, 0);" class=""><span style="font-variant-ligatures: no-common-ligatures; color: #000000" class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="font-variant-ligatures: no-common-ligatures" class="">// Since the row scope is present, let's assume that T will ask for</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(0, 132, 0);" class=""><span style="font-variant-ligatures: no-common-ligatures; color: #000000" class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="font-variant-ligatures: no-common-ligatures" class="">// a keyed container (a row scope). If T eventually asks for a</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(0, 132, 0);" class=""><span style="font-variant-ligatures: no-common-ligatures; color: #000000" class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="font-variant-ligatures: no-common-ligatures" class="">// single value container (a column), then the user will face a</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(0, 132, 0);" class=""><span style="font-variant-ligatures: no-common-ligatures; color: #000000" class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="font-variant-ligatures: no-common-ligatures" class="">// weird error.</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures" class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="font-variant-ligatures: no-common-ligatures; color: #ba2da2" class="">return</span><span style="font-variant-ligatures: no-common-ligatures" class=""> </span><span style="font-variant-ligatures: no-common-ligatures; color: #ba2da2" class="">try</span><span style="font-variant-ligatures: no-common-ligatures" class=""> </span><span style="font-variant-ligatures: no-common-ligatures; color: #4f8187" class="">T</span><span style="font-variant-ligatures: no-common-ligatures" class="">(from: RowDecoder(row: row, codingPath: codingPath + [key]))</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures" class="">&nbsp; &nbsp; &nbsp; &nbsp; } </span><span style="font-variant-ligatures: no-common-ligatures; color: #ba2da2" class="">else</span><span style="font-variant-ligatures: no-common-ligatures" class=""> {</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(0, 132, 0);" class=""><span style="font-variant-ligatures: no-common-ligatures; color: #000000" class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="font-variant-ligatures: no-common-ligatures" class="">// Both column and row scope are missing: we are sure that the value</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(0, 132, 0);" class=""><span style="font-variant-ligatures: no-common-ligatures; color: #000000" class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="font-variant-ligatures: no-common-ligatures" class="">// is missing.</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures" class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span><span style="font-variant-ligatures: no-common-ligatures; color: #ba2da2" class="">return</span><span style="font-variant-ligatures: no-common-ligatures" class=""> </span><span style="font-variant-ligatures: no-common-ligatures; color: #ba2da2" class="">nil</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures" class="">&nbsp; &nbsp; &nbsp; &nbsp; }</span></div><div style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;" class=""><span style="font-variant-ligatures: no-common-ligatures" class="">&nbsp; &nbsp; }</span></div></div><div><br class=""></div><div>But it's less than ideal, as expressed by the inline comments.</div><div><br class=""></div><div>We could discuss potential solutions, but I first hope that I was able to clearly express the topic.</div><div><br class=""></div><div>Gwendal</div><div><br class=""></div></div></div></div></div></div></body></html>