@@ -227,34 +227,46 @@ extension JSONDecoderImpl: Decoder {
227227 @usableFromInline func container< Key> ( keyedBy _: Key . Type ) throws ->
228228 KeyedDecodingContainer < Key > where Key: CodingKey
229229 {
230- guard case . object( let dictionary) = self . json else {
230+ switch self . json {
231+ case . object( let dictionary) :
232+ let container = KeyedContainer < Key > (
233+ impl: self ,
234+ codingPath: codingPath,
235+ dictionary: dictionary
236+ )
237+ return KeyedDecodingContainer ( container)
238+ case . null:
239+ throw DecodingError . valueNotFound ( [ String : JSONValue ] . self, DecodingError . Context (
240+ codingPath: self . codingPath,
241+ debugDescription: " Cannot get keyed decoding container -- found null value instead "
242+ ) )
243+ default :
231244 throw DecodingError . typeMismatch ( [ String : JSONValue ] . self, DecodingError . Context (
232245 codingPath: self . codingPath,
233246 debugDescription: " Expected to decode \( [ String : JSONValue ] . self) but found \( self . json. debugDataTypeDescription) instead. "
234247 ) )
235248 }
236-
237- let container = KeyedContainer < Key > (
238- impl: self ,
239- codingPath: codingPath,
240- dictionary: dictionary
241- )
242- return KeyedDecodingContainer ( container)
243249 }
244250
245251 @usableFromInline func unkeyedContainer( ) throws -> UnkeyedDecodingContainer {
246- guard case . array( let array) = self . json else {
252+ switch self . json {
253+ case . array( let array) :
254+ return UnkeyedContainer (
255+ impl: self ,
256+ codingPath: self . codingPath,
257+ array: array
258+ )
259+ case . null:
260+ throw DecodingError . valueNotFound ( [ String : JSONValue ] . self, DecodingError . Context (
261+ codingPath: self . codingPath,
262+ debugDescription: " Cannot get unkeyed decoding container -- found null value instead "
263+ ) )
264+ default :
247265 throw DecodingError . typeMismatch ( [ JSONValue ] . self, DecodingError . Context (
248266 codingPath: self . codingPath,
249267 debugDescription: " Expected to decode \( [ JSONValue ] . self) but found \( self . json. debugDataTypeDescription) instead. "
250268 ) )
251269 }
252-
253- return UnkeyedContainer (
254- impl: self ,
255- codingPath: self . codingPath,
256- array: array
257- )
258270 }
259271
260272 @usableFromInline func singleValueContainer( ) throws -> SingleValueDecodingContainer {
@@ -750,11 +762,11 @@ extension JSONDecoderImpl {
750762 }
751763
752764 func superDecoder( ) throws -> Decoder {
753- try decoderForKey ( _JSONKey. super)
765+ return decoderForKeyNoThrow ( _JSONKey. super)
754766 }
755767
756768 func superDecoder( forKey key: K ) throws -> Decoder {
757- try decoderForKey ( key)
769+ return decoderForKeyNoThrow ( key)
758770 }
759771
760772 private func decoderForKey< LocalKey: CodingKey > ( _ key: LocalKey ) throws -> JSONDecoderImpl {
@@ -770,6 +782,25 @@ extension JSONDecoderImpl {
770782 )
771783 }
772784
785+ private func decoderForKeyNoThrow< LocalKey: CodingKey > ( _ key: LocalKey ) -> JSONDecoderImpl {
786+ let value : JSONValue
787+ do {
788+ value = try getValue ( forKey: key)
789+ } catch {
790+ // if there no value for this key then return a null value
791+ value = . null
792+ }
793+ var newPath = self . codingPath
794+ newPath. append ( key)
795+
796+ return JSONDecoderImpl (
797+ userInfo: self . impl. userInfo,
798+ from: value,
799+ codingPath: newPath,
800+ options: self . impl. options
801+ )
802+ }
803+
773804 @inline ( __always) private func getValue< LocalKey: CodingKey > ( forKey key: LocalKey ) throws -> JSONValue {
774805 guard let value = dictionary [ key. stringValue] else {
775806 throw DecodingError . keyNotFound ( key, . init(
0 commit comments