Skip to content

Commit e1d202e

Browse files
committed
Improve empty array handling
Incorrect code was being generated for a JSON attribute whose value is an empty array.
1 parent 3a2d030 commit e1d202e

File tree

5 files changed

+31
-12
lines changed

5 files changed

+31
-12
lines changed

json2swift/failable-initializer-translation.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,9 +67,9 @@ fileprivate extension SwiftPrimitiveValueType {
6767
case .anything,
6868
.element,
6969
.elementArray,
70-
.emptyArray,
7170
.nullable,
7271
.valueArray: return .any
72+
case .emptyArray: return .emptyArray
7373
case .number(_, let isFloatingPoint): return isFloatingPoint ? .double : .int
7474
case .date(_, let format): return .date(format: format)
7575
case .url: return .url

json2swift/swift-code-generation.swift

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,7 @@ internal extension TransformationFromJSON {
246246
private static func letStatementForPrimitiveValue(_ attributeName: String, _ propertyName: String, _ type: SwiftPrimitiveValueType) -> LineOfCode {
247247
switch type {
248248
case .any: return "let \(propertyName) = json[\"\(attributeName)\"] as? Any"
249+
case .emptyArray: return "let \(propertyName) = json[\"\(attributeName)\"] as? [Any?]"
249250
case .bool, .int, .string: return "let \(propertyName) = json[\"\(attributeName)\"] as? \(type.name)"
250251
case .double: return "let \(propertyName) = Double(json: json, key: \"\(attributeName)\")" // Allows an integer to be interpreted as a double.
251252
case .url: return "let \(propertyName) = URL(json: json, key: \"\(attributeName)\")"
@@ -267,16 +268,17 @@ internal extension TransformationFromJSON {
267268

268269
private static func letStatementForArrayOfOptionalPrimitiveValues(_ attributeName: String, _ propertyName: String, _ elementType: SwiftPrimitiveValueType) -> LineOfCode {
269270
switch elementType {
270-
case .any, .bool, .int, .string: return "let \(propertyName) = (json[\"\(attributeName)\"] as? [Any]).map({ $0.toOptionalValueArray() as [\(elementType.name)?] })"
271-
case .date(let format): return "let \(propertyName) = (json[\"\(attributeName)\"] as? [Any]).map({ $0.toOptionalDateArray(withFormat: \"\(format)\") })"
272-
case .double: return "let \(propertyName) = (json[\"\(attributeName)\"] as? [Any]).map({ $0.toOptionalDoubleArray() })"
273-
case .url: return "let \(propertyName) = (json[\"\(attributeName)\"] as? [Any]).map({ $0.toOptionalURLArray() })"
271+
case .any, .bool, .int, .string, .emptyArray: return "let \(propertyName) = (json[\"\(attributeName)\"] as? [Any]).map({ $0.toOptionalValueArray() as [\(elementType.name)?] })"
272+
case .date(let format): return "let \(propertyName) = (json[\"\(attributeName)\"] as? [Any]).map({ $0.toOptionalDateArray(withFormat: \"\(format)\") })"
273+
case .double: return "let \(propertyName) = (json[\"\(attributeName)\"] as? [Any]).map({ $0.toOptionalDoubleArray() })"
274+
case .url: return "let \(propertyName) = (json[\"\(attributeName)\"] as? [Any]).map({ $0.toOptionalURLArray() })"
274275
}
275276
}
276277

277278
private static func letStatementForArrayOfRequiredPrimitiveValues(_ attributeName: String, _ propertyName: String, _ elementType: SwiftPrimitiveValueType) -> LineOfCode {
278279
switch elementType {
279280
case .any: return "let \(propertyName) = json[\"\(attributeName)\"] as? [Any?]" // Any is treated as optional.
281+
case .emptyArray: return "let \(propertyName) = json[\"\(attributeName)\"] as? [[Any?]]"
280282
case .bool, .int, .string: return "let \(propertyName) = json[\"\(attributeName)\"] as? [\(elementType.name)]"
281283
case .date(let format): return "let \(propertyName) = (json[\"\(attributeName)\"] as? [String]).flatMap({ $0.toDateArray(withFormat: \"\(format)\") })"
282284
case .double: return "let \(propertyName) = (json[\"\(attributeName)\"] as? [NSNumber]).map({ $0.toDoubleArray() })"
@@ -288,13 +290,14 @@ internal extension TransformationFromJSON {
288290
fileprivate extension SwiftPrimitiveValueType {
289291
var name: String {
290292
switch self {
291-
case .any: return "Any"
292-
case .bool: return "Bool"
293-
case .date: return "Date"
294-
case .double: return "Double"
295-
case .int: return "Int"
296-
case .string: return "String"
297-
case .url: return "URL"
293+
case .any: return "Any"
294+
case .bool: return "Bool"
295+
case .date: return "Date"
296+
case .double: return "Double"
297+
case .emptyArray: return "[Any?]"
298+
case .int: return "Int"
299+
case .string: return "String"
300+
case .url: return "URL"
298301
}
299302
}
300303
}

json2swift/swift-data-model.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,4 +55,5 @@ enum SwiftPrimitiveValueType {
5555
case string
5656
case bool
5757
case any
58+
case emptyArray
5859
}

unit_tests/swift-code-generation-primitive-array-tests.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,11 @@ class swift_code_generation_primitive_array_tests: XCTestCase {
3232
XCTAssertEqual(transformation.letStatement, "let p = (json[\"a\"] as? [NSNumber]).map({ $0.toDoubleArray() })")
3333
}
3434

35+
func test_array_of_required_emptyArray() {
36+
let transformation = TransformationFromJSON.toPrimitiveValueArray(attributeName: "a", propertyName: "p", elementType: .emptyArray, hasOptionalElements: false)
37+
XCTAssertEqual(transformation.letStatement, "let p = json[\"a\"] as? [[Any?]]")
38+
}
39+
3540
func test_array_of_required_int() {
3641
let transformation = TransformationFromJSON.toPrimitiveValueArray(attributeName: "a", propertyName: "p", elementType: .int, hasOptionalElements: false)
3742
XCTAssertEqual(transformation.letStatement, "let p = json[\"a\"] as? [Int]")
@@ -69,6 +74,11 @@ class swift_code_generation_primitive_array_tests: XCTestCase {
6974
XCTAssertEqual(transformation.letStatement, "let p = (json[\"a\"] as? [Any]).map({ $0.toOptionalDoubleArray() })")
7075
}
7176

77+
func test_array_of_optional_emptyArray() {
78+
let transformation = TransformationFromJSON.toPrimitiveValueArray(attributeName: "a", propertyName: "p", elementType: .emptyArray, hasOptionalElements: true)
79+
XCTAssertEqual(transformation.letStatement, "let p = (json[\"a\"] as? [Any]).map({ $0.toOptionalValueArray() as [[Any?]?] })")
80+
}
81+
7282
func test_array_of_optional_int() {
7383
let transformation = TransformationFromJSON.toPrimitiveValueArray(attributeName: "a", propertyName: "p", elementType: .int, hasOptionalElements: true)
7484
XCTAssertEqual(transformation.letStatement, "let p = (json[\"a\"] as? [Any]).map({ $0.toOptionalValueArray() as [Int?] })")

unit_tests/swift-code-generation-primitive-value-tests.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,11 @@ class swift_code_generation_primitive_value_tests: XCTestCase {
1414
XCTAssertEqual(transformation.letStatement, "let p = json[\"a\"] as? Any")
1515
}
1616

17+
func test_emptyArray() {
18+
let transformation = TransformationFromJSON.toPrimitiveValue(attributeName: "a", propertyName: "p", type: .emptyArray)
19+
XCTAssertEqual(transformation.letStatement, "let p = json[\"a\"] as? [Any?]")
20+
}
21+
1722
func test_bool() {
1823
let transformation = TransformationFromJSON.toPrimitiveValue(attributeName: "a", propertyName: "p", type: .bool)
1924
XCTAssertEqual(transformation.letStatement, "let p = json[\"a\"] as? Bool")

0 commit comments

Comments
 (0)