JSONEncoder and PropertyListEncoder both use NSNumber to box Bool values. An encoded Bool can be coerced to any numerical type during decoding because (false as NSNumber).intValue == 0. As a remedy, all of the unbox(_:as:) methods of _JSONDecoder and _PlistDecoder for numerical types include a check that the value is not identical to either kCFBooleanTrue or kCFBooleanFalse, and throw a DecodingError._typeMismatch(at:expectation:) if this check fails.
At the top level, JSONEncoder/PropertyListEncoder (and the decoders) directly encoded values into an encoder instead of following the logic to box the values (and thus dispatch based on the type, potentially intercepting representations or applying strategies). This led to top-level values having a different representation than similar values throughout a payload.
As a temporary workaround for SR-5206, certain Foundation types which had custom behavior in JSONEncoder and JSONDecoder were granted special knowledge of those types internally in order to preserve strategies on encode/decode.
This replaces that special knowledge with a more general-purpose fix that works for all types and all encoders/decoders.
{JSON,Plist}{Encoder,Decoder} had overlapping accesses which were supposed to be mutually exclusive in their `with(pushedKey:)` methods.
Removes those methods and the overlapping accesses.
One of the limitations of not having conditional conformance at the
moment is that the implementation of `init(from:)` and `encode(to:)` on
types which require it is that failure to cast dependent types to
`Encodable` or `Decodable` is a runtime failure. There is no way to
statically guarantee that the wrapped type is `Encodable` or
`Decodable`.
As such, in those implementations, at best we can directly call
`(element as! Encodable).encode(to: encoder)`, or similar. However, this
encodes the element directly into an encoder, without giving the encoder
a chance to intercept the type. This is problematic for `JSONEncoder`
because it cannot apply a strategy if it doesn't get to intercept the
type.
This gives a temporary workaround for JSON strategies because of
internal Foundation knowledge.
For the benefit of unkeyed containers, coding paths currently contain optional `CodingKey`s — unkeyed containers are allowed to report a `nil` key in a path. However, this is unhelpful for debugging purposes, or inspecting the coding path for context, since any unkeyed container simply reports `nil`, whether it’s at index 1 or 1000.
Now all containers are required to report a non-optional CodingKey for their segment of the coding path, and coding paths are now exposed as `[CodingKey]`.
If JSONSerialization or PropertyListSerialization throw errors during encoding or decoding, the error should be exposed as an EncodingError or DecodingError
* Add deferredToData strategy on encode and decode
* Rename base64{Encode,Decode} to base64 (missed this in previous fixes)
* Add unit test to confirm behavior
* Update {JSON,PropertyList}Decoder to allow superDecoder()s to wrap
null value so current implementations of collections can decode
contained objects from nil
To make it slightly easier to tell at a glance if a method is
implemented as part of API (public/open), shared implementation detail
(fileprivate), or implementation detail meaningful only to a given type
(private).
Allow JSONEncoder/JSONDecoder to intercept Decimal values so they get
a numeric representation in JSON (instead of their default keyed
implementation).
On encode, we previously treated every container request as a push;
instead, we should allow the same container type to be requested
multiple times so a class can pass its Encoder directly to its
superclass if it needs to.
SingleValueDecondingContainers in JSON and Plist previously held the
assertion that attempting to decode an array or dictionary from them
was a type mismatch (since those represented unkeyed and keyed
containers, respectively). This assertion is no longer true, though,
since encode<T : Encodable>(_:) and decode<T : Decodable>(_:) allow
you to do just that.
This lifts the assertion and adds unit tests to both implementations to
ensure this works. (Addresses https://bugs.swift.org/browse/SR-5089)
* Adds conformance of Optional to Codable
* encode(...) arguments are no longer Optional; Optional values go
through generic version
* encodeIfPresent added to KeyedEncodingContainerProtocol to mirror
decodeIfPresent
* JSONEncoder and PropertyListEncoder updated to reflect these changes
codingPath more often than not actually needs to be copied, not just
referenced. This makes a big difference for nested containers and
subobjects, which were getting the wrong codingPath values when asking
for them.
This also adds unit tests for JSONEncoder and PropertyListEncoder to
confirm expected behavior.
* Integrate {JSON,PropertyList}{Encoder,Decoder} types to facilitate
encoding types in JSON and property list formats
* Adds Foundation-specific extensions to allow errors exposed from the
stdlib to bridge to NSErrors