Skip to content

Commit e670d09

Browse files
author
Alexander Sporn
committed
Add support for decoding Int and Double from a String representing a double or int
1 parent d9c3427 commit e670d09

File tree

2 files changed

+51
-6
lines changed

2 files changed

+51
-6
lines changed

Sources/JSONDecodable.swift

+16
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,12 @@ extension Double: JSONDecodable {
3232
self = double
3333
case let .Int(int):
3434
self = Swift.Double(int)
35+
case let .String(string):
36+
if let double = Swift.Double(string) where double <= Double(Swift.Int.max) {
37+
self = double
38+
return
39+
}
40+
fallthrough
3541
default:
3642
throw JSON.Error.ValueNotConvertible(value: json, to: Swift.Double)
3743
}
@@ -52,6 +58,16 @@ extension Int: JSONDecodable {
5258
self = Swift.Int(double)
5359
case let .Int(int):
5460
self = int
61+
case let .String(string):
62+
if let double = Swift.Double(string) where double <= Double(Swift.Int.max) && Swift.Double(Swift.Int(double)) == double {
63+
self = Swift.Int(double)
64+
return
65+
}
66+
else if let int = Swift.Int(string) {
67+
self = int
68+
return
69+
}
70+
fallthrough
5571
default:
5672
throw JSON.Error.ValueNotConvertible(value: json, to: Swift.Int)
5773
}

Tests/JSONDecodableTests.swift

+35-6
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,8 @@ class JSONDecodableTests: XCTestCase {
3939
let fourPointFour = 4.4
4040
let fourPointFourJSON: JSON = 4.4
4141
let fourJSON: JSON = 4
42-
42+
let fourPointFourStringJSON: JSON = "4.4"
43+
4344
do {
4445
let decodedFourPointFour = try Double(json: fourPointFourJSON)
4546
let decodedFour = try Double(json: fourJSON)
@@ -48,10 +49,17 @@ class JSONDecodableTests: XCTestCase {
4849
} catch {
4950
XCTFail("Should be able to instantiate a `Double` with `JSON`: \(error).")
5051
}
51-
52+
53+
do {
54+
let decodedFourPointFour = try Double(json: fourPointFourStringJSON)
55+
XCTAssertEqual(decodedFourPointFour, fourPointFour, "`fourPointFour` and '4.4' `String` should be equal.")
56+
} catch {
57+
XCTFail("Failed for unknown reason: \(error).")
58+
}
59+
5260
do {
5361
_ = try Double(json: "bad")
54-
XCTFail("Should not be able to instantiate `Double` with `String` `JSON`.")
62+
XCTFail("Should not be able to instantiate `Double` with `String` not matching a double representation `JSON`.")
5563
} catch JSON.Error.ValueNotConvertible(let type) {
5664
XCTAssert(true, "\(type) should not be covertible from 'bad' `String`.")
5765
} catch {
@@ -63,7 +71,10 @@ class JSONDecodableTests: XCTestCase {
6371
let four = 4
6472
let fourJSON: JSON = 4
6573
let fourPointZeroJSON: JSON = 4.0
66-
74+
let fourStringJSON: JSON = "4"
75+
let fourPointZeroStringJSON: JSON = "4.0"
76+
let fourPointFourStringJSON: JSON = "4.4"
77+
6778
do {
6879
let decodedFour = try Int(json: fourJSON)
6980
let decodedFourPointZero = try Int(json: fourPointZeroJSON)
@@ -72,10 +83,28 @@ class JSONDecodableTests: XCTestCase {
7283
} catch {
7384
XCTFail("Should be able to instantiate an `Int` with `JSON`: \(error).")
7485
}
75-
86+
87+
do {
88+
let decodedFour = try Int(json: fourStringJSON)
89+
let decodedFourPointZero = try Int(json: fourPointZeroStringJSON)
90+
XCTAssertEqual(decodedFour, four, "`four` and '4' `String` should be equal.")
91+
XCTAssertEqual(decodedFourPointZero, four, "`decodedFourPointZero` and '4.0' `String` should be equal.")
92+
} catch {
93+
XCTFail("Failed for unknown reason: \(error).")
94+
}
95+
96+
do {
97+
_ = try Int(json: fourPointFourStringJSON)
98+
XCTFail("Should not be able to instantiate `Int` with '4.4' `String` `JSON`.")
99+
} catch JSON.Error.ValueNotConvertible(let type) {
100+
XCTAssert(true, "\(type) should not be covertible from '4.4' `String`.")
101+
} catch {
102+
XCTFail("Failed for unknown reason: \(error).")
103+
}
104+
76105
do {
77106
_ = try Int(json: "bad")
78-
XCTFail("Should not be able to instantiate `Int` with `String` `JSON`.")
107+
XCTFail("Should not be able to instantiate `Int` with `String` not matching an integer representation `JSON`.")
79108
} catch JSON.Error.ValueNotConvertible(let type) {
80109
XCTAssert(true, "\(type) should not be covertible from 'bad' `String`.")
81110
} catch {

0 commit comments

Comments
 (0)