Skip to content

Commit ca6eb5f

Browse files
committed
Add collection decoding support.
1 parent 1ce483f commit ca6eb5f

File tree

2 files changed

+86
-1
lines changed

2 files changed

+86
-1
lines changed

Sources/Coding/Decoding.swift

+19
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,25 @@ public extension Decoding where Value: Decodable {
9090
return try container.decodeIfPresent(Value.self, forKey: key)
9191
}
9292
}
93+
94+
static var array: Decoding<[Value]> {
95+
Decoding<Value>.arrayOf(.singleValue)
96+
}
97+
}
98+
99+
// MARK: - Collections
100+
101+
public extension Decoding {
102+
static func arrayOf(_ decoding: Self) -> Decoding<[Value]> {
103+
.init { decoder in
104+
var container = try decoder.unkeyedContainer()
105+
var result: [Value] = []
106+
while !container.isAtEnd {
107+
try result.append(decoding.decode(container.superDecoder()))
108+
}
109+
return result
110+
}
111+
}
93112
}
94113

95114
// MARK: - Zip

Tests/CodingTests/DecodingTests.swift

+67-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ final class DecodingTests: XCTestCase {
88
case value
99
}
1010

11-
struct User {
11+
struct User: Equatable {
1212
var name: String
1313
var age: Int
1414
var city: String?
@@ -96,6 +96,72 @@ final class DecodingTests: XCTestCase {
9696
XCTAssertEqual("Unknown", user.city)
9797
}
9898

99+
// MARK: - Decoding collections
100+
101+
func testDecodingArrayOfSimpleValues() throws {
102+
let json = """
103+
[
104+
"one",
105+
"two",
106+
"three"
107+
]
108+
"""
109+
110+
let strings = try decoder.decode(
111+
json.data(using: .utf8)!,
112+
as: Decoding<String>.array
113+
)
114+
115+
XCTAssertEqual(["one", "two", "three"], strings)
116+
117+
let uppercased = try decoder.decode(
118+
json.data(using: .utf8)!,
119+
as: Decoding<String>.arrayOf(.singleValue.map { $0.uppercased() })
120+
)
121+
122+
XCTAssertEqual(["ONE", "TWO", "THREE"], uppercased)
123+
}
124+
125+
func testDecodingArrayOfComplexValues() throws {
126+
let json = """
127+
[
128+
{
129+
"name": "Joe Bloggs",
130+
"age": 18
131+
},
132+
{
133+
"name": "Jane Doe",
134+
"age": 21,
135+
"city": "London"
136+
}
137+
]
138+
"""
139+
140+
let name = Decoding<String>
141+
.withKey(User.CodingKeys.name)
142+
143+
let age = Decoding<Int>
144+
.withKey(User.CodingKeys.age)
145+
146+
let city = Decoding<String>
147+
.optionalWithKey(User.CodingKeys.city)
148+
149+
let user = zip(with: User.init)(name, age, city)
150+
151+
let users = try decoder.decode(
152+
json.data(using: .utf8)!,
153+
as: Decoding<User>.arrayOf(user)
154+
)
155+
156+
XCTAssertEqual(
157+
users,
158+
[
159+
User(name: "Joe Bloggs", age: 18, city: nil),
160+
User(name: "Jane Doe", age: 21, city: "London")
161+
]
162+
)
163+
}
164+
99165
// MARK: - Built-in decodings
100166

101167
func testDecoding_UInt16() throws {

0 commit comments

Comments
 (0)