From 63f07dc16887e3bb0b02a33a4b37d27af62c9327 Mon Sep 17 00:00:00 2001 From: TizianoCoroneo <15340382+TizianoCoroneo@users.noreply.github.com> Date: Mon, 23 Feb 2026 16:58:06 +0100 Subject: [PATCH] feat: new strategy to skip encoding nested containers --- .../Encoder/DictionaryComponentEncoder.swift | 3 +++ Sources/Encoder/DictionaryEncoder.swift | 9 ++++++++- .../Options/DictionaryEncodingOptions.swift | 1 + .../DictionaryNestedEncodingStrategy.swift | 9 +++++++++ .../DictionaryEncoderStrategiesTests.swift | 19 +++++++++++++++++++ 5 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 Sources/Encoder/Options/DictionaryNestedEncodingStrategy.swift diff --git a/Sources/Encoder/DictionaryComponentEncoder.swift b/Sources/Encoder/DictionaryComponentEncoder.swift index f9198e8..5866acb 100644 --- a/Sources/Encoder/DictionaryComponentEncoder.swift +++ b/Sources/Encoder/DictionaryComponentEncoder.swift @@ -208,6 +208,9 @@ extension DictionaryComponentEncoder { case let url as URL: return try encodeURL(url, at: codingPath) + case _ where self.options.nestedEncodingStrategy == .skip: + return .value(nil) + default: return try encodeNonPrimitiveValue(value, at: codingPath) } diff --git a/Sources/Encoder/DictionaryEncoder.swift b/Sources/Encoder/DictionaryEncoder.swift index d424b99..2430135 100644 --- a/Sources/Encoder/DictionaryEncoder.swift +++ b/Sources/Encoder/DictionaryEncoder.swift @@ -32,6 +32,11 @@ public final class DictionaryEncoder: Sendable { set { optionsMutex.withLock { $0.keyEncodingStrategy = newValue } } } + public var nestedEncodingStrategy: DictionaryNestedEncodingStrategy { + get { optionsMutex.withLock { $0.nestedEncodingStrategy } } + set { optionsMutex.withLock { $0.nestedEncodingStrategy = newValue } } + } + public var userInfo: [CodingUserInfoKey: Sendable] { get { userInfoMutex.withLock { $0 } } set { userInfoMutex.withLock { $0 = newValue } } @@ -45,6 +50,7 @@ public final class DictionaryEncoder: Sendable { nonConformingFloatEncodingStrategy: DictionaryNonConformingFloatEncodingStrategy = .throw, nilEncodingStrategy: DictionaryNilEncodingStrategy = .useNil, keyEncodingStrategy: DictionaryKeyEncodingStrategy = .useDefaultKeys, + nestedEncodingStrategy: DictionaryNestedEncodingStrategy = .encode, userInfo: [CodingUserInfoKey: Sendable] = [:] ) { let options = DictionaryEncodingOptions( @@ -52,7 +58,8 @@ public final class DictionaryEncoder: Sendable { dataEncodingStrategy: dataEncodingStrategy, nonConformingFloatEncodingStrategy: nonConformingFloatEncodingStrategy, nilEncodingStrategy: nilEncodingStrategy, - keyEncodingStrategy: keyEncodingStrategy + keyEncodingStrategy: keyEncodingStrategy, + nestedEncodingStrategy: nestedEncodingStrategy ) self.optionsMutex = Mutex(value: options) diff --git a/Sources/Encoder/Options/DictionaryEncodingOptions.swift b/Sources/Encoder/Options/DictionaryEncodingOptions.swift index 6878ada..f369236 100644 --- a/Sources/Encoder/Options/DictionaryEncodingOptions.swift +++ b/Sources/Encoder/Options/DictionaryEncodingOptions.swift @@ -9,4 +9,5 @@ internal struct DictionaryEncodingOptions { internal var nonConformingFloatEncodingStrategy: DictionaryNonConformingFloatEncodingStrategy internal var nilEncodingStrategy: DictionaryNilEncodingStrategy internal var keyEncodingStrategy: DictionaryKeyEncodingStrategy + internal var nestedEncodingStrategy: DictionaryNestedEncodingStrategy } diff --git a/Sources/Encoder/Options/DictionaryNestedEncodingStrategy.swift b/Sources/Encoder/Options/DictionaryNestedEncodingStrategy.swift new file mode 100644 index 0000000..da0a299 --- /dev/null +++ b/Sources/Encoder/Options/DictionaryNestedEncodingStrategy.swift @@ -0,0 +1,9 @@ +import Foundation + +public enum DictionaryNestedEncodingStrategy: Sendable { + + // MARK: - Enumeration Cases + + case encode + case skip +} diff --git a/Tests/Encoder/DictionaryEncoderStrategiesTests.swift b/Tests/Encoder/DictionaryEncoderStrategiesTests.swift index 6f0b642..9625944 100644 --- a/Tests/Encoder/DictionaryEncoderStrategiesTests.swift +++ b/Tests/Encoder/DictionaryEncoderStrategiesTests.swift @@ -219,6 +219,25 @@ final class DictionaryEncoderStrategiesTests: XCTestCase, DictionaryEncoderTesti assertEncoderSucceeds(encoding: EncodableStruct()) } + // MARK: - + + func testThatEncoderSucceedsWhenSkippingNestedContainers() { + struct EncodableStruct: Encodable { + var test: String = "1" + var dict: [String: Int] = ["a": 1] + var array: [String] = ["b"] + } + + encoder.nestedEncodingStrategy = .skip + + assertEncoderSucceeds( + encoding: EncodableStruct(), + expecting: [ + "test": "1" + ]) + } + + // MARK: - XCTestCase override func setUp() {