```swift
enum IntOrString: Equatable {
case int(Int)
case string(String)
}
extension IntOrString: Encodable {
enum CodingKeys: String, CodingKey {
case int
case string
}
func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
switch self {
case let .int(value):
try container.encode(value, forKey: .int)
case let .string(value):
try container.encode(value, forKey: .string)
}
}
}
extension IntOrString.CodingKeys: XMLChoiceCodingKey {} // signifies that `IntOrString` is a choice element
```
Implementation Details
In cases where choice and non-choice elements (or multiple choice elements) co-exist in a keyed container, we merge them into a single XMLKeyedEncodingContainer (wrapping a SharedBox<KeyedBox>). Arrays of choice elements (using XMLUnkeyedEncodingContainer under the hood) are encoded the same way as before, as we do not hit the merging cases. For the array case, we still need the XMLChoiceEncodingContainer structure.
Overview
Fixes bug encountered when encoding structs that hold a mixture of choice-element and non-choice-element (or multiple choice-element) properties.
Example
Given a structure that stores both a choice and non-choice property,
the natural encoding approach (now available) is
The following
encode
implementation also works```swift extension IntOrStringAndDouble: Encodable { enum CodingKeys: String, CodingKey { case decimal } func encode(to encoder: Encoder) { var singleValueContainer = encoder.singleValueContainer() try singleValueContainer.encode(intOrString) var container = encoder.container(keyedBy: CodingKeys.self) try container.encode(decimal, forKey: .decimal) } } ```
IntOrString
as defined in #119```swift enum IntOrString: Equatable { case int(Int) case string(String) } extension IntOrString: Encodable { enum CodingKeys: String, CodingKey { case int case string } func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) switch self { case let .int(value): try container.encode(value, forKey: .int) case let .string(value): try container.encode(value, forKey: .string) } } } extension IntOrString.CodingKeys: XMLChoiceCodingKey {} // signifies that `IntOrString` is a choice element ```
Implementation Details
In cases where choice and non-choice elements (or multiple choice elements) co-exist in a keyed container, we merge them into a single
XMLKeyedEncodingContainer
(wrapping aSharedBox<KeyedBox>
). Arrays of choice elements (usingXMLUnkeyedEncodingContainer
under the hood) are encoded the same way as before, as we do not hit the merging cases. For the array case, we still need theXMLChoiceEncodingContainer
structure.Source Compatibility
This is an additive change.