@@ -227,34 +227,46 @@ extension JSONDecoderImpl: Decoder {
227
227
@usableFromInline func container< Key> ( keyedBy _: Key . Type ) throws ->
228
228
KeyedDecodingContainer < Key > where Key: CodingKey
229
229
{
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 :
231
244
throw DecodingError . typeMismatch ( [ String : JSONValue ] . self, DecodingError . Context (
232
245
codingPath: self . codingPath,
233
246
debugDescription: " Expected to decode \( [ String : JSONValue ] . self) but found \( self . json. debugDataTypeDescription) instead. "
234
247
) )
235
248
}
236
-
237
- let container = KeyedContainer < Key > (
238
- impl: self ,
239
- codingPath: codingPath,
240
- dictionary: dictionary
241
- )
242
- return KeyedDecodingContainer ( container)
243
249
}
244
250
245
251
@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 :
247
265
throw DecodingError . typeMismatch ( [ JSONValue ] . self, DecodingError . Context (
248
266
codingPath: self . codingPath,
249
267
debugDescription: " Expected to decode \( [ JSONValue ] . self) but found \( self . json. debugDataTypeDescription) instead. "
250
268
) )
251
269
}
252
-
253
- return UnkeyedContainer (
254
- impl: self ,
255
- codingPath: self . codingPath,
256
- array: array
257
- )
258
270
}
259
271
260
272
@usableFromInline func singleValueContainer( ) throws -> SingleValueDecodingContainer {
@@ -750,11 +762,11 @@ extension JSONDecoderImpl {
750
762
}
751
763
752
764
func superDecoder( ) throws -> Decoder {
753
- try decoderForKey ( _JSONKey. super)
765
+ return decoderForKeyNoThrow ( _JSONKey. super)
754
766
}
755
767
756
768
func superDecoder( forKey key: K ) throws -> Decoder {
757
- try decoderForKey ( key)
769
+ return decoderForKeyNoThrow ( key)
758
770
}
759
771
760
772
private func decoderForKey< LocalKey: CodingKey > ( _ key: LocalKey ) throws -> JSONDecoderImpl {
@@ -770,6 +782,25 @@ extension JSONDecoderImpl {
770
782
)
771
783
}
772
784
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
+
773
804
@inline ( __always) private func getValue< LocalKey: CodingKey > ( forKey key: LocalKey ) throws -> JSONValue {
774
805
guard let value = dictionary [ key. stringValue] else {
775
806
throw DecodingError . keyNotFound ( key, . init(
0 commit comments