Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 38c47ea

Browse files
committed
Merge pull request swiftlang#99 from cezarywojcik/master
NSJSONSerialization isValidJSONObject Implementation
2 parents ea3014b + c5e0f21 commit 38c47ea

File tree

4 files changed

+171
-11
lines changed

4 files changed

+171
-11
lines changed

Foundation.xcodeproj/project.pbxproj

100644100755
Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,7 @@
198198
5BF7AEC11BCD51F9008F214A /* NSValue.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BDC3F4C1BCC5DCB00ED97BB /* NSValue.swift */; };
199199
61F8AE7D1C180FC600FB62F0 /* TestNSNotificationCenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61F8AE7C1C180FC600FB62F0 /* TestNSNotificationCenter.swift */; };
200200
7A7D6FBB1C16439400957E2E /* TestNSURLResponse.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A7D6FBA1C16439400957E2E /* TestNSURLResponse.swift */; };
201+
5EB6A15D1C188FC40037DCB8 /* TestNSJSONSerialization.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5EB6A15C1C188FC40037DCB8 /* TestNSJSONSerialization.swift */; };
201202
83712C8E1C1684900049AD49 /* TestNSURLRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 83712C8D1C1684900049AD49 /* TestNSURLRequest.swift */; };
202203
844DC3331C17584F005611F9 /* TestNSScanner.swift in Sources */ = {isa = PBXBuildFile; fileRef = 844DC3321C17584F005611F9 /* TestNSScanner.swift */; };
203204
848A30581C137B3500C83206 /* TestNSHTTPCookie.swift in Sources */ = {isa = PBXBuildFile; fileRef = 848A30571C137B3500C83206 /* TestNSHTTPCookie.swift */; };
@@ -534,6 +535,7 @@
534535
5BF7AEC21BCD568D008F214A /* ForSwiftFoundationOnly.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ForSwiftFoundationOnly.h; sourceTree = "<group>"; };
535536
61F8AE7C1C180FC600FB62F0 /* TestNSNotificationCenter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestNSNotificationCenter.swift; sourceTree = "<group>"; };
536537
7A7D6FBA1C16439400957E2E /* TestNSURLResponse.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestNSURLResponse.swift; sourceTree = "<group>"; };
538+
5EB6A15C1C188FC40037DCB8 /* TestNSJSONSerialization.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestNSJSONSerialization.swift; sourceTree = "<group>"; };
537539
83712C8D1C1684900049AD49 /* TestNSURLRequest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestNSURLRequest.swift; sourceTree = "<group>"; };
538540
844DC3321C17584F005611F9 /* TestNSScanner.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestNSScanner.swift; sourceTree = "<group>"; };
539541
848A30571C137B3500C83206 /* TestNSHTTPCookie.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = TestNSHTTPCookie.swift; path = TestFoundation/TestNSHTTPCookie.swift; sourceTree = SOURCE_ROOT; };
@@ -631,7 +633,6 @@
631633
EADE0B8D1BD15DFF00C49C64 /* NSXMLNode.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NSXMLNode.swift; sourceTree = "<group>"; };
632634
EADE0B8E1BD15DFF00C49C64 /* NSXMLNodeOptions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NSXMLNodeOptions.swift; sourceTree = "<group>"; };
633635
EADE0B8F1BD15DFF00C49C64 /* NSXMLParser.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NSXMLParser.swift; sourceTree = "<group>"; };
634-
ED58F76E1C134B3A00E6A5BE /* TestNSJSONSerialization.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestNSJSONSerialization.swift; sourceTree = "<group>"; };
635636
/* End PBXFileReference section */
636637

637638
/* Begin PBXFrameworksBuildPhase section */
@@ -1046,6 +1047,7 @@
10461047
525AECEB1BF2C96400D15BB0 /* TestNSFileManager.swift */,
10471048
88D28DE61C13AE9000494606 /* TestNSGeometry.swift */,
10481049
EA66F63E1BF1619600136161 /* TestNSIndexSet.swift */,
1050+
5EB6A15C1C188FC40037DCB8 /* TestNSJSONSerialization.swift */,
10491051
EA66F63F1BF1619600136161 /* TestNSNumber.swift */,
10501052
4DC1D07F1C12EEEF00B5948A /* TestNSPipe.swift */,
10511053
EA66F6401BF1619600136161 /* TestNSPropertyList.swift */,
@@ -1763,6 +1765,7 @@
17631765
22B9C1E11C165D7A00DECFF9 /* TestNSDate.swift in Sources */,
17641766
848A30581C137B3500C83206 /* TestNSHTTPCookie.swift in Sources */,
17651767
EA66F6541BF1619600136161 /* TestNSSet.swift in Sources */,
1768+
5EB6A15D1C188FC40037DCB8 /* TestNSJSONSerialization.swift in Sources */,
17661769
EA66F64A1BF1619600136161 /* TestNSArray.swift in Sources */,
17671770
5BC1D8BE1BF3B09E009D3973 /* TestNSCharacterSet.swift in Sources */,
17681771
EA66F6561BF1619600136161 /* TestNSString.swift in Sources */,

Foundation/NSJSONSerialization.swift

Lines changed: 55 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -28,20 +28,66 @@ public struct NSJSONWritingOptions : OptionSetType {
2828
/* A class for converting JSON to Foundation/Swift objects and converting Foundation/Swift objects to JSON.
2929

3030
An object that may be converted to JSON must have the following properties:
31-
- Top level object is an Array or Dictionary
32-
- All objects are String, NSNumber, Array, Dictionary, or NSNull
33-
- All dictionary keys are Strings
34-
- NSNumbers are not NaN or infinity
31+
- Top level object is a `Swift.Array` or `Swift.Dictionary`
32+
- All objects are `Swift.String`, `Foundation.NSNumber`, `Swift.Array`, `Swift.Dictionary`,
33+
or `Foundation.NSNull`
34+
- All dictionary keys are `Swift.String`s
35+
- `NSNumber`s are not NaN or infinity
3536
*/
3637

3738
public class NSJSONSerialization : NSObject {
3839

39-
/* Returns YES if the given object can be converted to JSON data, NO otherwise.
40-
41-
Other rules may apply. Calling this method or attempting a conversion are the definitive ways to tell if a given object can be converted to JSON data.
40+
/* Determines whether the given object can be converted to JSON.
41+
Other rules may apply. Calling this method or attempting a conversion are the definitive ways
42+
to tell if a given object can be converted to JSON data.
43+
- parameter obj: The object to test.
44+
- returns: `true` if `obj` can be converted to JSON, otherwise `false`.
4245
*/
43-
public class func isValidJSONObject(obj: AnyObject) -> Bool {
44-
NSUnimplemented()
46+
public class func isValidJSONObject(obj: Any) -> Bool {
47+
// TODO: - revisit this once bridging story gets fully figured out
48+
func isValidJSONObjectInternal(obj: Any) -> Bool {
49+
// object is Swift.String or NSNull
50+
if obj is String || obj is NSNull {
51+
return true
52+
}
53+
54+
// object is NSNumber and is not NaN or infinity
55+
if let number = obj as? NSNumber {
56+
let invalid = number.doubleValue.isInfinite || number.doubleValue.isNaN
57+
|| number.floatValue.isInfinite || number.floatValue.isNaN
58+
return !invalid
59+
}
60+
61+
// object is Swift.Array
62+
if let array = obj as? [Any] {
63+
for element in array {
64+
guard isValidJSONObjectInternal(element) else {
65+
return false
66+
}
67+
}
68+
return true
69+
}
70+
71+
// object is Swift.Dictionary
72+
if let dictionary = obj as? [String: Any] {
73+
for (_, value) in dictionary {
74+
guard isValidJSONObjectInternal(value) else {
75+
return false
76+
}
77+
}
78+
return true
79+
}
80+
81+
// invalid object
82+
return false
83+
}
84+
85+
// top level object must be an Swift.Array or Swift.Dictionary
86+
guard obj is [Any] || obj is [String: Any] else {
87+
return false
88+
}
89+
90+
return isValidJSONObjectInternal(obj)
4591
}
4692

4793
/* Generate JSON data from a Foundation object. If the object will not produce valid JSON then an exception will be thrown. Setting the NSJSONWritingPrettyPrinted option will generate JSON with whitespace designed to make the output more readable. If that option is not set, the most compact possible JSON will be generated. If an error occurs, the error parameter will be set and the return value will be nil. The resulting data is a encoded in UTF-8.

TestFoundation/TestNSJSONSerialization.swift

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,14 @@ class TestNSJSONSerialization : XCTestCase {
2222
var allTests : [(String, () -> ())] {
2323
return JSONObjectWithDataTests
2424
+ deserializationTests
25+
+ isValidJSONObjectTests
2526
}
2627

2728
}
2829

2930
//MARK: - JSONObjectWithData
3031
extension TestNSJSONSerialization {
32+
3133
var JSONObjectWithDataTests: [(String, () -> ())] {
3234
return [
3335
("test_JSONObjectWithData_emptyObject", test_JSONObjectWithData_emptyObject),
@@ -70,6 +72,7 @@ extension TestNSJSONSerialization {
7072
XCTAssertNotNil(result, description)
7173
}
7274
}
75+
7376
}
7477

7578
//MARK: - JSONDeserialization
@@ -392,4 +395,113 @@ extension TestNSJSONSerialization {
392395
// Passing case; the unicode character is malformed
393396
}
394397
}
398+
399+
}
400+
401+
// MARK: - isValidJSONObjectTests
402+
extension TestNSJSONSerialization {
403+
404+
var isValidJSONObjectTests: [(String, () -> ())] {
405+
return [
406+
("test_isValidJSONObjectTrue", test_isValidJSONObjectTrue),
407+
("test_isValidJSONObjectFalse", test_isValidJSONObjectFalse),
408+
]
409+
}
410+
411+
func test_isValidJSONObjectTrue() {
412+
let trueJSON: [Any] = [
413+
// []
414+
Array<Any>(),
415+
416+
// [1, ["string", [[]]]]
417+
Array<Any>(arrayLiteral:
418+
NSNumber(int: 1),
419+
Array<Any>(arrayLiteral:
420+
"string",
421+
Array<Any>(arrayLiteral:
422+
Array<Any>()
423+
)
424+
)
425+
),
426+
427+
// [NSNull(), ["1" : ["string", 1], "2" : NSNull()]]
428+
Array<Any>(arrayLiteral:
429+
NSNull(),
430+
Dictionary<String, Any>(dictionaryLiteral:
431+
(
432+
"1",
433+
Array<Any>(arrayLiteral:
434+
"string",
435+
NSNumber(int: 1)
436+
)
437+
),
438+
(
439+
"2",
440+
NSNull()
441+
)
442+
)
443+
),
444+
445+
// ["0" : 0]
446+
Dictionary<String, Any>(dictionaryLiteral:
447+
(
448+
"0",
449+
NSNumber(int: 0)
450+
)
451+
)
452+
]
453+
for testCase in trueJSON {
454+
XCTAssertTrue(NSJSONSerialization.isValidJSONObject(testCase))
455+
}
456+
}
457+
458+
func test_isValidJSONObjectFalse() {
459+
let falseJSON: [Any] = [
460+
// 0
461+
NSNumber(int: 0),
462+
463+
// NSNull()
464+
NSNull(),
465+
466+
// "string"
467+
"string",
468+
469+
// [1, 2, 3, [4 : 5]]
470+
Array<Any>(arrayLiteral:
471+
NSNumber(int: 1),
472+
NSNumber(int: 2),
473+
NSNumber(int: 3),
474+
Dictionary<NSNumber, Any>(dictionaryLiteral:
475+
(
476+
NSNumber(int: 4),
477+
NSNumber(int: 5)
478+
)
479+
)
480+
),
481+
482+
// [1, 2, Infinity]
483+
[NSNumber(int: 1), NSNumber(int: 2), NSNumber(double: 1 / 0)],
484+
485+
// [NSNull() : 1]
486+
[NSNull() : NSNumber(int: 1)],
487+
488+
// [[[[1 : 2]]]]
489+
Array<Any>(arrayLiteral:
490+
Array<Any>(arrayLiteral:
491+
Array<Any>(arrayLiteral:
492+
Dictionary<NSNumber, Any>(dictionaryLiteral:
493+
(
494+
NSNumber(int: 1),
495+
NSNumber(int: 2)
496+
)
497+
)
498+
)
499+
)
500+
)
501+
]
502+
for testCase in falseJSON {
503+
XCTAssertFalse(NSJSONSerialization.isValidJSONObject(testCase))
504+
}
505+
}
506+
395507
}

TestFoundation/main.swift

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@ XCTMain([
4141
TestNSData(),
4242
TestNSTimeZone(),
4343
TestNSScanner(),
44-
TestNSJSONSerialization(),
4544
TestNSURLRequest(),
4645
TestNSHTTPCookie(),
4746
TestNSGeometry(),

0 commit comments

Comments
 (0)