Skip to content

Commit 4a53225

Browse files
authored
Merge pull request #4 from LiveUI/singletonList
Fix to handle singleton lists with ListDecodingStrategy.
2 parents f5d46f4 + 7786903 commit 4a53225

2 files changed

Lines changed: 59 additions & 2 deletions

File tree

Sources/XMLCoding/Decoder/XMLUnkeyedDecodingContainer.swift

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,16 @@ internal struct _XMLUnkeyedDecodingContainer : UnkeyedDecodingContainer {
3737
case .collapseListUsingItemTag(let itemTag):
3838
if container.count == 1,
3939
let itemKeyMap = container[0] as? [AnyHashable: Any],
40-
let list = itemKeyMap[itemTag] as? [Any] {
41-
self.container = list
40+
let entry = itemKeyMap[itemTag] {
41+
// if there are multiple items in the list,
42+
// the entry will be a list
43+
if let list = entry as? [Any] {
44+
self.container = list
45+
} else {
46+
// otherwise it will be the singleton entry;
47+
// place it in a list for the container
48+
self.container = [entry]
49+
}
4250
} else {
4351
self.container = []
4452
}

Tests/XMLCodingTests/XMLParsingTests.swift

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,17 @@ let LIST_XML = """
1818
</Response>
1919
"""
2020

21+
let SINGLETON_LIST_XML = """
22+
<Response>
23+
<Result />
24+
<MetadataList>
25+
<item>
26+
<Id>id1</Id>
27+
</item>
28+
</MetadataList>
29+
</Response>
30+
"""
31+
2132
class XMLParsingTests: XCTestCase {
2233
struct Result: Codable {
2334
let message: String?
@@ -130,6 +141,22 @@ class XMLParsingTests: XCTestCase {
130141
XCTAssertEqual(LIST_XML, encodedString)
131142
}
132143

144+
func testSingletonListDecodingWithDefaultStrategy() throws {
145+
guard let inputData = SINGLETON_LIST_XML.data(using: .utf8) else {
146+
return XCTFail()
147+
}
148+
149+
let response = try XMLDecoder().decode(ResponseWithList.self, from: inputData)
150+
151+
XCTAssertEqual(1, response.metadataList.items.count)
152+
153+
// encode the output to make sure we get what we started with
154+
let data = try XMLEncoder().encode(response, withRootKey: "Response")
155+
let encodedString = String(data: data, encoding: .utf8) ?? ""
156+
157+
XCTAssertEqual(SINGLETON_LIST_XML, encodedString)
158+
}
159+
133160
func testListDecodingWithCollapseItemTagStrategy() throws {
134161
guard let inputData = LIST_XML.data(using: .utf8) else {
135162
return XCTFail()
@@ -150,11 +177,33 @@ class XMLParsingTests: XCTestCase {
150177

151178
XCTAssertEqual(LIST_XML, encodedString)
152179
}
180+
181+
func testSingletonListDecodingWithCollapseItemTagStrategy() throws {
182+
guard let inputData = SINGLETON_LIST_XML.data(using: .utf8) else {
183+
return XCTFail()
184+
}
185+
186+
let decoder = XMLDecoder()
187+
decoder.listDecodingStrategy = .collapseListUsingItemTag("item")
188+
let response = try decoder.decode(ResponseWithCollapsedList.self, from: inputData)
189+
190+
XCTAssertEqual(1, response.metadataList.count)
191+
192+
let encoder = XMLEncoder()
193+
encoder.listEncodingStrategy = .expandListWithItemTag("item")
194+
195+
// encode the output to make sure we get what we started with
196+
let data = try encoder.encode(response, withRootKey: "Response")
197+
let encodedString = String(data: data, encoding: .utf8) ?? ""
198+
199+
XCTAssertEqual(SINGLETON_LIST_XML, encodedString)
200+
}
153201

154202
static var allTests = [
155203
("testEmptyElement", testEmptyElement),
156204
("testEmptyElementNotEffectingPreviousElement", testEmptyElementNotEffectingPreviousElement),
157205
("testListDecodingWithDefaultStrategy", testListDecodingWithDefaultStrategy),
206+
("testSingletonListDecodingWithDefaultStrategy", testSingletonListDecodingWithDefaultStrategy),
158207
("testListDecodingWithCollapseItemTagStrategy", testListDecodingWithCollapseItemTagStrategy)
159208
]
160209
}

0 commit comments

Comments
 (0)