# \[Pitch\] JSONDecoder.nullDecodingStrategy

**URL:** <https://forums.swift.org/t/pitch-jsondecoder-nulldecodingstrategy/13980>\
**Category:** Pitches\
**Tags:** codable, json, optional\
**Created:** [June 25, 2018, 8:17pm UTC](https://forums.swift.org/t/pitch-jsondecoder-nulldecodingstrategy/13980 "2018-06-25T20:17:11Z")\
**Posts on this page:** 1\
**Showing post:** 13

<div class="post-metadata">

**Author:** ![itaiferber](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/itaiferber/32/33840_2.png) [@itaiferber](https://forums.swift.org/u/itaiferber)\
**Post date:** [November 15, 2024, 8:02pm UTC](https://forums.swift.org/t/pitch-jsondecoder-nulldecodingstrategy/13980/13 "2024-11-15T20:02:11Z")

</div>

> [@tera](#):
>
> Edit: this fails to decode json with absent key:
> 
> `{"one":1,"two":"2","four":4}`

Yes, for the same reason above: compiler synthesis only generates `decodeIfPresent()` calls for `Optional`. We've, er, [had this discussion before](https://forums.swift.org/t/optional-decoding-superpowers/63649), [on more than one occasion](https://forums.swift.org/t/decoding-of-optionals-missing-in-json/52475) 😅

* * *

> [@swhitty](#):
>
> An extension on `KeyedDecodingContainer` is required to decode wrapped or custom optional types.

Although this works, it's _very_ important to understand why and how it works, and take into account that this is a _very_ fragile solution that is hard to recommend.

An extension to `KeyedDecodingContainer` only works because:

1. `Codable` compiler synthesis currently manipulates the AST directly, generating code _as-if_ you had written the source code yourself; because of this, actual resolution of method overloads allows type checking to select more specific overloads for specific calls (e.g., those found in extensions)
2. An extension in your module makes that overload available for the compiler to select _within_ your module (and modules you make it visible to)

It's _really_ important to keep in mind that **this does not actually change the _behavior_ of `KeyedDecodingContainer` at all** , just that it monkey-patches a new overload of the method with the same name that makes it visible at synthesis time. This means that:

1. Modules which don't have this extension at compile-time will **silently** behave differently from ones that do. This can happen when, e.g.,
  - Module `A` declares an `internal` extension, and Module `B` encodes and decodes the same type
  - Module `A` declares a `public` extension, but Module `B` is compiled before it and encodes and decodes the same type

2. You can accidentally and silently end up in situation (1) by moving types/extensions between sibling modules
3. You can't override behavior for modules you don't control
4. If other modules also define a similar extension, their version will win out over yours when they compile
5. If compiler synthesis changes (e.g., it starts performing `Codable` method lookup only in the stdlib), this is liable to silently break

---

_[View the full topic](https://forums.swift.org/t/pitch-jsondecoder-nulldecodingstrategy/13980)._
