Skip to content

Commit 79efe7b

Browse files
authored
Add JSON.isArray and JSON.isObject (#9)
1 parent 5634965 commit 79efe7b

File tree

4 files changed

+142
-43
lines changed

4 files changed

+142
-43
lines changed

.github/workflows/ci.yml

+3-3
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,11 @@ on: push
44

55
jobs:
66
test:
7-
runs-on: macos-13
7+
runs-on: macos-14
88

99
steps:
1010
- uses: actions/checkout@v3
11-
- name: Select Xcode 15
12-
run: sudo xcode-select -s /Applications/Xcode_15.0.app
11+
- name: Select Xcode 16
12+
run: sudo xcode-select -s /Applications/Xcode_16.0.app
1313
- name: Test
1414
run: swift test

Sources/JSON/Dictionary+JSON.swift

+20-20
Original file line numberDiff line numberDiff line change
@@ -3,67 +3,67 @@ import Foundation
33
public extension [String: Any] {
44
func boolValue(forKey key: String) -> Bool? {
55
if let v = self[key] as? Bool {
6-
return v
6+
v
77
} else if let v = self[key] as? NSNumber, v.isBool {
8-
return v.boolValue
8+
v.boolValue
99
} else {
10-
return nil
10+
nil
1111
}
1212
}
1313

1414
func doubleValue(forKey key: String) -> Double? {
1515
if let v = self[key] as? Double {
16-
return v
16+
v
1717
} else if let v = self[key] as? NSNumber, !v.isBool {
18-
return v.doubleValue
18+
v.doubleValue
1919
} else {
20-
return nil
20+
nil
2121
}
2222
}
2323

2424
func intValue(forKey key: String) -> Int? {
2525
if let v = self[key] as? Int {
26-
return v
26+
v
2727
} else if let v = self[key] as? Double {
28-
return Int(v)
28+
Int(v)
2929
} else if let v = self[key] as? NSNumber, !v.isBool {
30-
return v.intValue
30+
v.intValue
3131
} else {
32-
return nil
32+
nil
3333
}
3434
}
3535
}
3636

3737
public extension [String: Any]? {
3838
func boolValue(forKey key: String) -> Bool? {
3939
if let v = self?[key] as? Bool {
40-
return v
40+
v
4141
} else if let v = self?[key] as? NSNumber, v.isBool {
42-
return v.boolValue
42+
v.boolValue
4343
} else {
44-
return nil
44+
nil
4545
}
4646
}
4747

4848
func doubleValue(forKey key: String) -> Double? {
4949
if let v = self?[key] as? Double {
50-
return v
50+
v
5151
} else if let v = self?[key] as? NSNumber, !v.isBool {
52-
return v.doubleValue
52+
v.doubleValue
5353
} else {
54-
return nil
54+
nil
5555
}
5656
}
5757

5858
func intValue(forKey key: String) -> Int? {
5959
if let v = self?[key] as? Int {
60-
return v
60+
v
6161
} else if let v = self?[key] as? Double {
62-
return Int(v)
62+
Int(v)
6363
} else if let v = self?[key] as? NSNumber, !v.isBool {
64-
return v.intValue
64+
v.intValue
6565
} else {
66-
return nil
66+
nil
6767
}
6868
}
6969
}

Sources/JSON/JSON.swift

+43-20
Original file line numberDiff line numberDiff line change
@@ -150,22 +150,22 @@ public enum JSON:
150150
public var rawValue: Any {
151151
switch self {
152152
case let .array(array):
153-
return array.map(\.rawValue)
153+
array.map(\.rawValue)
154154

155155
case let .boolean(bool):
156-
return bool
156+
bool
157157

158158
case let .dictionary(dictionary):
159-
return dictionary.mapValues(\.rawValue)
159+
dictionary.mapValues(\.rawValue)
160160

161161
case .null:
162-
return NSNull()
162+
NSNull()
163163

164164
case let .number(number):
165-
return number
165+
number
166166

167167
case let .string(string):
168-
return string
168+
string
169169
}
170170
}
171171

@@ -203,9 +203,9 @@ public enum JSON:
203203
/// underlying type is `.number`, otherwise `nil`.
204204
public var integerValue: Int? {
205205
if let double = rawValue as? Double {
206-
return Int(double)
206+
Int(double)
207207
} else {
208-
return nil
208+
nil
209209
}
210210
}
211211

@@ -216,6 +216,19 @@ public enum JSON:
216216
return string
217217
}
218218

219+
/// Returns `true` if the receiver is an array, otherwise `false`.
220+
public var isArray: Bool {
221+
guard case .array = self else { return false }
222+
return true
223+
}
224+
225+
/// Returns `true` if the receiver is a JSON object (a "dictionary"),
226+
/// otherwise `false`.
227+
public var isObject: Bool {
228+
guard case .dictionary = self else { return false }
229+
return true
230+
}
231+
219232
public var description: String {
220233
String(describing: rawValue)
221234
}
@@ -280,25 +293,25 @@ extension JSON: Equatable {
280293
public static func == (_ arg1: JSON, _ arg2: JSON) -> Bool {
281294
switch (arg1, arg2) {
282295
case let (.array(one), .array(two)):
283-
return one == two
296+
one == two
284297

285298
case let (.boolean(one), .boolean(two)):
286-
return one == two
299+
one == two
287300

288301
case let (.dictionary(one), .dictionary(two)):
289-
return one == two
302+
one == two
290303

291304
case let (.number(one), .number(two)):
292-
return one == two
305+
one == two
293306

294307
case (.null, .null):
295-
return true
308+
true
296309

297310
case let (.string(one), .string(two)):
298-
return one == two
311+
one == two
299312

300313
default:
301-
return false
314+
false
302315
}
303316
}
304317
}
@@ -508,9 +521,9 @@ public extension JSON? {
508521
/// underlying type is `.number`, otherwise `nil`.
509522
var integerValue: Int? {
510523
if let double = self?.rawValue as? Double {
511-
return Int(double)
524+
Int(double)
512525
} else {
513-
return nil
526+
nil
514527
}
515528
}
516529

@@ -521,6 +534,19 @@ public extension JSON? {
521534
return string
522535
}
523536

537+
/// Returns `true` if the receiver is an array, otherwise `false`.
538+
var isArray: Bool {
539+
guard let self, self.isArray else { return false }
540+
return true
541+
}
542+
543+
/// Returns `true` if the receiver is a JSON object (a "dictionary"),
544+
/// otherwise `false`.
545+
var isObject: Bool {
546+
guard let self, self.isObject else { return false }
547+
return true
548+
}
549+
524550
static func == (_ arg1: JSON, _ arg2: JSON?) -> Bool {
525551
guard let arg2 else { return false }
526552
return arg1 == arg2
@@ -620,7 +646,6 @@ private extension Any? {
620646
case let e as NSNumber where e.isBool: return .boolean(e.boolValue)
621647
case let e as NSNumber: return .number(e.doubleValue)
622648
case let e as String: return .string(e)
623-
624649
// The above cases should catch everything, but, in case they
625650
// don't, we try remaining types here.
626651
case let e as Bool: return .boolean(e)
@@ -637,9 +662,7 @@ private extension Any? {
637662
case let e as UInt16: return .number(Double(e))
638663
case let e as UInt32: return .number(Double(e))
639664
case let e as UInt64: return .number(Double(e))
640-
641665
case let e as JSON: return e
642-
643666
default: return nil
644667
}
645668
}

Tests/JSONTests/JSONTests.swift

+76
Original file line numberDiff line numberDiff line change
@@ -339,4 +339,80 @@ final class JSONTests: XCTestCase {
339339
}
340340
XCTAssertEqual(dict, mixed)
341341
}
342+
343+
func testIsArray() throws {
344+
let array: JSON = ["one", 2, 3.0, true, nil]
345+
XCTAssertTrue(array.isArray)
346+
347+
let object: JSON = ["one": 1, "two": 2, "three": 3]
348+
XCTAssertFalse(object.isArray)
349+
350+
let string: JSON = "string"
351+
XCTAssertFalse(string.isArray)
352+
353+
let number: JSON = 123
354+
XCTAssertFalse(number.isArray)
355+
356+
let bool: JSON = true
357+
XCTAssertFalse(bool.isArray)
358+
359+
let null: JSON = nil
360+
XCTAssertFalse(null.isArray)
361+
362+
let optionalArray: JSON? = ["one", 2, 3.0, true, nil]
363+
XCTAssertTrue(optionalArray.isArray)
364+
365+
let optionalObject: JSON? = ["one": 1, "two": 2, "three": 3]
366+
XCTAssertFalse(optionalObject.isArray)
367+
368+
let optionalString: JSON? = "string"
369+
XCTAssertFalse(optionalString.isArray)
370+
371+
let optionalNumber: JSON? = 123
372+
XCTAssertFalse(optionalNumber.isArray)
373+
374+
let optionalBool: JSON? = true
375+
XCTAssertFalse(optionalBool.isArray)
376+
377+
let optionalNull: JSON? = nil
378+
XCTAssertFalse(optionalNull.isArray)
379+
}
380+
381+
func testIsObject() throws {
382+
let array: JSON = ["one", 2, 3.0, true, nil]
383+
XCTAssertFalse(array.isObject)
384+
385+
let object: JSON = ["one": 1, "two": 2, "three": 3]
386+
XCTAssertTrue(object.isObject)
387+
388+
let string: JSON = "string"
389+
XCTAssertFalse(string.isObject)
390+
391+
let number: JSON = 123
392+
XCTAssertFalse(number.isObject)
393+
394+
let bool: JSON = true
395+
XCTAssertFalse(bool.isObject)
396+
397+
let null: JSON = nil
398+
XCTAssertFalse(null.isObject)
399+
400+
let optionalArray: JSON? = ["one", 2, 3.0, true, nil]
401+
XCTAssertFalse(optionalArray.isObject)
402+
403+
let optionalObject: JSON? = ["one": 1, "two": 2, "three": 3]
404+
XCTAssertTrue(optionalObject.isObject)
405+
406+
let optionalString: JSON? = "string"
407+
XCTAssertFalse(optionalString.isObject)
408+
409+
let optionalNumber: JSON? = 123
410+
XCTAssertFalse(optionalNumber.isObject)
411+
412+
let optionalBool: JSON? = true
413+
XCTAssertFalse(optionalBool.isObject)
414+
415+
let optionalNull: JSON? = nil
416+
XCTAssertFalse(optionalNull.isObject)
417+
}
342418
}

0 commit comments

Comments
 (0)