@@ -149,102 +149,114 @@ public class NSJSONSerialization : NSObject {
149
149
}
150
150
}
151
151
// MARK: - Serialization
152
- private extension NSJSONSerialization
153
- {
154
- private class func escapeStringForJSON( string: String ) -> String
155
- {
156
- // TODO: Escape control characters \u{0} to \u{20} in string as required by RFC
152
+ private extension NSJSONSerialization {
153
+
154
+ private class func escapeStringForJSON( string: String ) -> String {
157
155
return NSString ( NSString ( string) . stringByReplacingOccurrencesOfString ( " \\ " , withString: " \\ \\ " ) ) . stringByReplacingOccurrencesOfString ( " \" " , withString: " \\ \" " )
158
156
}
159
- private class func serializeArray< T> ( array: [ T ] , newIndent: String , newLine: String , space: String , indentation: String ) throws -> String
160
- {
157
+ private class func serializeArray< T> ( array: [ T ] , newIndent: String , newLine: String , space: String , indentation: String ) throws -> String {
161
158
guard array. count > 0
162
- else
163
- {
159
+ else {
164
160
return " \( indentation) [] "
165
161
}
166
162
var index = 0
167
163
return try array. reduce ( " \( indentation) [ \( newLine) " , combine: {
168
- ++ index
164
+ index += 1
169
165
let separator = ( index == array. count) ? " \( newLine) \( indentation) ] " : " , \( newLine) "
170
166
return $0 + ( try JSONSerialize ( $1, newIndent: newIndent, newLine: newLine, space: space, indentation: indentation + newIndent) ) + separator
171
167
} )
172
168
}
173
169
174
- private class func serializePOD( object: Any ) throws -> String
175
- {
176
- if let str = object as? String
177
- {
178
- return " \" \( escapeStringForJSON ( str) ) \" "
179
- }
180
- else if let num = object as? Double
181
- {
182
- // FIXME: Use NSNumber once API is fixed
183
- // Detect numeric type and use true, false keywords or integer type if not double
184
- return " \( num) "
185
- }
186
- else if let _ = object as? NSNull
187
- {
188
- return " null "
189
- }
190
- else
191
- {
192
- throw NSCocoaError . PropertyListWriteInvalidError
170
+ private class func serializePOD< T: Any > ( object: T , indentation: String ) throws -> String {
171
+ if let str = object as? String {
172
+ return indentation + " \" \( escapeStringForJSON ( str) ) \" "
173
+ } else if let _ = object as? NSNull {
174
+ return indentation + " null "
175
+ } else if let obj = object as? CustomStringConvertible {
176
+ // Using CustomStringConvertible is a hack to allow for all POD types
177
+ // Once bridging works we can revert back.
178
+ // TODO: Fix when bridging works
179
+ return indentation + escapeStringForJSON( obj. description)
180
+ }
181
+ else if let num = object as? NSNumber {
182
+ return num. description
183
+ } else {
184
+ throw NSError ( domain: NSCocoaErrorDomain, code: NSCocoaError . PropertyListWriteInvalidError. rawValue, userInfo: [
185
+ " NSDebugDescription " : " Cannot serialize \( object. dynamicType) "
186
+ ] )
193
187
}
194
188
}
195
189
196
- private class func serializeObject< T> ( object: [ String : T ] , newIndent: String , newLine: String , space: String , indentation: String ) throws -> String
197
- {
190
+ private class func serializeObject< T> ( object: [ String : T ] , newIndent: String , newLine: String , space: String , indentation: String ) throws -> String {
198
191
guard object. count > 0
199
- else
200
- {
192
+ else {
201
193
return " \( indentation) {} "
202
194
}
203
195
var index = 0
204
196
return try object. reduce ( " \( indentation) { \( newLine) " , combine: {
205
197
let valueString : String
206
- do
207
- {
208
- valueString = try serializePOD ( $1. 1 )
198
+ do {
199
+ valueString = try serializePOD ( $1. 1 , indentation: " " )
209
200
}
210
- catch
211
- {
201
+ catch {
212
202
valueString = try JSONSerialize ( $1. 1 , newIndent: newIndent, newLine: newLine, space: space, indentation: indentation + newIndent)
213
203
}
214
- ++ index
204
+ index += 1
215
205
let separator = ( index == object. count) ? " \( newLine) \( indentation) } " : " , \( newLine) "
216
206
return $0 + " \( indentation + newIndent) \" " + escapeStringForJSON( $1. 0 ) + " \" \( space) : \( space) " + valueString + separator
217
207
} )
218
208
}
219
209
220
- private class func JSONSerialize( object: Any , newIndent: String , newLine: String , space: String , topLevel: Bool = false , indentation: String = " " ) throws -> String
221
- {
222
- if let array = object as? [ Any ]
223
- {
210
+ private class func JSONSerialize< T> ( object: T , newIndent: String , newLine: String , space: String , topLevel: Bool = false , indentation: String = " " ) throws -> String {
211
+ // TODO: - revisit this once bridging story gets fully figured out
212
+ if let array = object as? [ Any ] {
224
213
return try serializeArray ( array, newIndent: newIndent, newLine: newLine, space: space, indentation: indentation)
225
- }
226
- else if let dict = object as? [ String : Any ]
227
- {
214
+ } else if let array = object as? NSArray {
215
+ return try serializeArray ( array. bridge ( ) , newIndent: newIndent, newLine: newLine, space: space, indentation: indentation)
216
+ } else if let array = object as? [ NSNumber ] {
217
+ return try serializeArray ( array, newIndent: newIndent, newLine: newLine, space: space, indentation: indentation)
218
+ } else if let array = object as? [ String ] {
219
+ return try serializeArray ( array, newIndent: newIndent, newLine: newLine, space: space, indentation: indentation)
220
+ } else if let array = object as? [ Double ] {
221
+ return try serializeArray ( array, newIndent: newIndent, newLine: newLine, space: space, indentation: indentation)
222
+ } else if let array = object as? [ Int ] {
223
+ return try serializeArray ( array, newIndent: newIndent, newLine: newLine, space: space, indentation: indentation)
224
+ } else if let array = object as? [ Bool ] {
225
+ return try serializeArray ( array, newIndent: newIndent, newLine: newLine, space: space, indentation: indentation)
226
+ } else if let array = object as? [ Float ] {
227
+ return try serializeArray ( array, newIndent: newIndent, newLine: newLine, space: space, indentation: indentation)
228
+ } else if let array = object as? [ UInt ] {
229
+ return try serializeArray ( array, newIndent: newIndent, newLine: newLine, space: space, indentation: indentation)
230
+ } else if let dict = object as? [ String : Any ] {
231
+ return try serializeObject ( dict, newIndent: newIndent, newLine: newLine, space: space, indentation: indentation)
232
+ } else if let dict = object as? NSDictionary {
233
+ return try JSONSerialize ( dict. bridge ( ) , newIndent: newIndent, newLine: newLine, space: space, topLevel: topLevel, indentation: indentation)
234
+ } else if let dict = object as? [ String : String ] {
235
+ return try serializeObject ( dict, newIndent: newIndent, newLine: newLine, space: space, indentation: indentation)
236
+ } else if let dict = object as? [ String : Double ] {
237
+ return try serializeObject ( dict, newIndent: newIndent, newLine: newLine, space: space, indentation: indentation)
238
+ } else if let dict = object as? [ String : Int ] {
239
+ return try serializeObject ( dict, newIndent: newIndent, newLine: newLine, space: space, indentation: indentation)
240
+ } else if let dict = object as? [ String : Bool ] {
241
+ return try serializeObject ( dict, newIndent: newIndent, newLine: newLine, space: space, indentation: indentation)
242
+ } else if let dict = object as? [ String : Float ] {
243
+ return try serializeObject ( dict, newIndent: newIndent, newLine: newLine, space: space, indentation: indentation)
244
+ } else if let dict = object as? [ String : UInt ] {
245
+ return try serializeObject ( dict, newIndent: newIndent, newLine: newLine, space: space, indentation: indentation)
246
+ } else if let dict = object as? [ String : NSNumber ] {
228
247
return try serializeObject ( dict, newIndent: newIndent, newLine: newLine, space: space, indentation: indentation)
229
248
}
230
- else if let array = object as? NSArray
231
- {
232
- // FIXME: Warns that NSArray can't be casted to [AnyObject]
233
- return try serializeArray ( array as! [ AnyObject ] , newIndent: newIndent, newLine: newLine, space: space, indentation: indentation)
234
- }
235
- else if let dict = object as? NSDictionary
236
- {
237
- // FIXME: Warns that NSArray can't be casted to [String: AnyObject]
238
- return try serializeObject ( dict as! [ String : AnyObject ] , newIndent: newIndent, newLine: newLine, space: space, indentation: indentation)
239
- }
240
- else
241
- {
249
+ // This else if situation will greatly improve once bridging works properly.
250
+ // For now we check for Floats, Doubles, Int, UInt, Bool and NSNumber
251
+ // but this may disallow other types like CGFloat, Int32, etc which is a problem
252
+ else {
242
253
guard !topLevel
243
- else
244
- {
245
- throw NSCocoaError . PropertyListWriteInvalidError
254
+ else {
255
+ throw NSError ( domain: NSCocoaErrorDomain, code: NSCocoaError . PropertyListWriteInvalidError. rawValue, userInfo: [
256
+ " NSDebugDescription " : " Unable to use \( object. dynamicType) as a top level JSON object. "
257
+ ] )
246
258
}
247
- return try serializePOD ( object)
259
+ return try serializePOD ( object, indentation : indentation )
248
260
}
249
261
}
250
262
}
0 commit comments