-
Notifications
You must be signed in to change notification settings - Fork 214
Description
Describe the bug
Default behaviour of Decodable types with optionals is to treat missing key or null value as expected cases which are parsed to nil without error.
This behaviour seems to be expected for DecodableWithConfiguration types as per implementation for Optionals (See extension Optional : DecodableWithConfiguration where Wrapped : DecodableWithConfiguration)
CodableConfiguration decoding behaviour for Optional types is inconsistent with both Codable as well as DecodableWithConfiguration types for which null value for a key is treated as decoding error.
To Reproduce
Sample code to reproduce the behavior.
CodableConfiguration protocol requirements implementation:
import Foundation
public struct NonCodableType {
public let value: String
public init(value: String) {
self.value = value
}
}
/// Helper object allowing to decode Date using ISO8601 scheme
public struct CustomConfig: DecodingConfigurationProviding, EncodingConfigurationProviding, Sendable {
public static let encodingConfiguration = CustomConfig()
public static let decodingConfiguration = CustomConfig()
func decode(from decoder: any Decoder) throws -> NonCodableType {
let container = try decoder.singleValueContainer()
let value = try container.decode(String.self)
return NonCodableType(value: value)
}
func encode(object: NonCodableType, to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
try container.encode(object.value)
}
}
extension NonCodableType: CodableWithConfiguration {
public init(from decoder: any Decoder, configuration: CustomConfig) throws {
self = try configuration.decode(from: decoder)
}
public func encode(to encoder: any Encoder, configuration: CustomConfig) throws {
try configuration.encode(object: self, to: encoder)
}
}Example code surfacing issue
import Foundation
struct TestModel: Codable {
@CodableConfiguration(wrappedValue: nil, from: CustomConfig.self)
var testObject: NonCodableType?
}
let json = "{\"testObject\": null}"
let jsonData = json.data(using: .utf8)!
let decoder = JSONDecoder()
// Fails with valueNotFound
let sut = try decoder.decode(TestModel.self, from: jsonData)Above is part of example reproduction that I kept in separate repo: https://github.com/TomaszLizer/CodableConfiguration-Tests
Expected behavior
Similarly to Codable decoding with Optional types I would expect above to succeed and nil value be assigned without error
Configuration (please complete the following information):
Tested with below configurations
- Swift Version: Swift 6.2; Swift 6.1
- OS: iOS; macOS
- OS Version: iOS 18; iOS 26; macOS 15
Regression information:
Seems there is no regression and that is behaviour from the beginning (at leat in this repo based on GIT blame search.
Additional context
N/A