You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1563 lines
43 KiB

6 years ago
  1. // SwiftyJSON.swift
  2. //
  3. // Copyright (c) 2014 - 2017 Ruoyu Fu, Pinglin Tang
  4. //
  5. // Permission is hereby granted, free of charge, to any person obtaining a copy
  6. // of this software and associated documentation files (the "Software"), to deal
  7. // in the Software without restriction, including without limitation the rights
  8. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  9. // copies of the Software, and to permit persons to whom the Software is
  10. // furnished to do so, subject to the following conditions:
  11. //
  12. // The above copyright notice and this permission notice shall be included in
  13. // all copies or substantial portions of the Software.
  14. //
  15. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  18. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  20. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  21. // THE SOFTWARE.
  22. import Foundation
  23. // MARK: - Error
  24. // swiftlint:disable line_length
  25. /// Error domain
  26. @available(*, deprecated, message: "ErrorDomain is deprecated. Use `SwiftyJSONError.errorDomain` instead.", renamed: "SwiftyJSONError.errorDomain")
  27. public let ErrorDomain: String = "SwiftyJSONErrorDomain"
  28. /// Error code
  29. @available(*, deprecated, message: "ErrorUnsupportedType is deprecated. Use `SwiftyJSONError.unsupportedType` instead.", renamed: "SwiftyJSONError.unsupportedType")
  30. public let ErrorUnsupportedType: Int = 999
  31. @available(*, deprecated, message: "ErrorIndexOutOfBounds is deprecated. Use `SwiftyJSONError.indexOutOfBounds` instead.", renamed: "SwiftyJSONError.indexOutOfBounds")
  32. public let ErrorIndexOutOfBounds: Int = 900
  33. @available(*, deprecated, message: "ErrorWrongType is deprecated. Use `SwiftyJSONError.wrongType` instead.", renamed: "SwiftyJSONError.wrongType")
  34. public let ErrorWrongType: Int = 901
  35. @available(*, deprecated, message: "ErrorNotExist is deprecated. Use `SwiftyJSONError.notExist` instead.", renamed: "SwiftyJSONError.notExist")
  36. public let ErrorNotExist: Int = 500
  37. @available(*, deprecated, message: "ErrorInvalidJSON is deprecated. Use `SwiftyJSONError.invalidJSON` instead.", renamed: "SwiftyJSONError.invalidJSON")
  38. public let ErrorInvalidJSON: Int = 490
  39. public enum SwiftyJSONError: Int, Swift.Error {
  40. case unsupportedType = 999
  41. case indexOutOfBounds = 900
  42. case elementTooDeep = 902
  43. case wrongType = 901
  44. case notExist = 500
  45. case invalidJSON = 490
  46. }
  47. extension SwiftyJSONError: CustomNSError {
  48. /// return the error domain of SwiftyJSONError
  49. public static var errorDomain: String { return "com.swiftyjson.SwiftyJSON" }
  50. /// return the error code of SwiftyJSONError
  51. public var errorCode: Int { return self.rawValue }
  52. /// return the userInfo of SwiftyJSONError
  53. public var errorUserInfo: [String: Any] {
  54. switch self {
  55. case .unsupportedType:
  56. return [NSLocalizedDescriptionKey: "It is an unsupported type."]
  57. case .indexOutOfBounds:
  58. return [NSLocalizedDescriptionKey: "Array Index is out of bounds."]
  59. case .wrongType:
  60. return [NSLocalizedDescriptionKey: "Couldn't merge, because the JSONs differ in type on top level."]
  61. case .notExist:
  62. return [NSLocalizedDescriptionKey: "Dictionary key does not exist."]
  63. case .invalidJSON:
  64. return [NSLocalizedDescriptionKey: "JSON is invalid."]
  65. case .elementTooDeep:
  66. return [NSLocalizedDescriptionKey: "Element too deep. Increase maxObjectDepth and make sure there is no reference loop."]
  67. }
  68. }
  69. }
  70. // MARK: - JSON Type
  71. /**
  72. JSON's type definitions.
  73. See http://www.json.org
  74. */
  75. public enum Type: Int {
  76. case number
  77. case string
  78. case bool
  79. case array
  80. case dictionary
  81. case null
  82. case unknown
  83. }
  84. // MARK: - JSON Base
  85. public struct JSON {
  86. /**
  87. Creates a JSON using the data.
  88. - parameter data: The NSData used to convert to json.Top level object in data is an NSArray or NSDictionary
  89. - parameter opt: The JSON serialization reading options. `[]` by default.
  90. - returns: The created JSON
  91. */
  92. public init(data: Data, options opt: JSONSerialization.ReadingOptions = []) throws {
  93. let object: Any = try JSONSerialization.jsonObject(with: data, options: opt)
  94. self.init(jsonObject: object)
  95. }
  96. /**
  97. Creates a JSON object
  98. - note: this does not parse a `String` into JSON, instead use `init(parseJSON: String)`
  99. - parameter object: the object
  100. - returns: the created JSON object
  101. */
  102. public init(_ object: Any) {
  103. switch object {
  104. case let object as Data:
  105. do {
  106. try self.init(data: object)
  107. } catch {
  108. self.init(jsonObject: NSNull())
  109. }
  110. default:
  111. self.init(jsonObject: object)
  112. }
  113. }
  114. /**
  115. Parses the JSON string into a JSON object
  116. - parameter json: the JSON string
  117. - returns: the created JSON object
  118. */
  119. public init(parseJSON jsonString: String) {
  120. if let data = jsonString.data(using: .utf8) {
  121. self.init(data)
  122. } else {
  123. self.init(NSNull())
  124. }
  125. }
  126. /**
  127. Creates a JSON from JSON string
  128. - parameter json: Normal json string like '{"a":"b"}'
  129. - returns: The created JSON
  130. */
  131. @available(*, deprecated, message: "Use instead `init(parseJSON: )`")
  132. public static func parse(_ json: String) -> JSON {
  133. return json.data(using: String.Encoding.utf8)
  134. .flatMap { try? JSON(data: $0) } ?? JSON(NSNull())
  135. }
  136. /**
  137. Creates a JSON using the object.
  138. - parameter jsonObject: The object must have the following properties: All objects are NSString/String, NSNumber/Int/Float/Double/Bool, NSArray/Array, NSDictionary/Dictionary, or NSNull; All dictionary keys are NSStrings/String; NSNumbers are not NaN or infinity.
  139. - returns: The created JSON
  140. */
  141. fileprivate init(jsonObject: Any) {
  142. self.object = jsonObject
  143. }
  144. /**
  145. Merges another JSON into this JSON, whereas primitive values which are not present in this JSON are getting added,
  146. present values getting overwritten, array values getting appended and nested JSONs getting merged the same way.
  147. - parameter other: The JSON which gets merged into this JSON
  148. - throws `ErrorWrongType` if the other JSONs differs in type on the top level.
  149. */
  150. public mutating func merge(with other: JSON) throws {
  151. try self.merge(with: other, typecheck: true)
  152. }
  153. /**
  154. Merges another JSON into this JSON and returns a new JSON, whereas primitive values which are not present in this JSON are getting added,
  155. present values getting overwritten, array values getting appended and nested JSONS getting merged the same way.
  156. - parameter other: The JSON which gets merged into this JSON
  157. - throws `ErrorWrongType` if the other JSONs differs in type on the top level.
  158. - returns: New merged JSON
  159. */
  160. public func merged(with other: JSON) throws -> JSON {
  161. var merged = self
  162. try merged.merge(with: other, typecheck: true)
  163. return merged
  164. }
  165. /**
  166. Private woker function which does the actual merging
  167. Typecheck is set to true for the first recursion level to prevent total override of the source JSON
  168. */
  169. fileprivate mutating func merge(with other: JSON, typecheck: Bool) throws {
  170. if self.type == other.type {
  171. switch self.type {
  172. case .dictionary:
  173. for (key, _) in other {
  174. try self[key].merge(with: other[key], typecheck: false)
  175. }
  176. case .array:
  177. self = JSON(self.arrayValue + other.arrayValue)
  178. default:
  179. self = other
  180. }
  181. } else {
  182. if typecheck {
  183. throw SwiftyJSONError.wrongType
  184. } else {
  185. self = other
  186. }
  187. }
  188. }
  189. /// Private object
  190. fileprivate var rawArray: [Any] = []
  191. fileprivate var rawDictionary: [String: Any] = [:]
  192. fileprivate var rawString: String = ""
  193. fileprivate var rawNumber: NSNumber = 0
  194. fileprivate var rawNull: NSNull = NSNull()
  195. fileprivate var rawBool: Bool = false
  196. /// JSON type, fileprivate setter
  197. public fileprivate(set) var type: Type = .null
  198. /// Error in JSON, fileprivate setter
  199. public fileprivate(set) var error: SwiftyJSONError?
  200. /// Object in JSON
  201. public var object: Any {
  202. get {
  203. switch self.type {
  204. case .array:
  205. return self.rawArray
  206. case .dictionary:
  207. return self.rawDictionary
  208. case .string:
  209. return self.rawString
  210. case .number:
  211. return self.rawNumber
  212. case .bool:
  213. return self.rawBool
  214. default:
  215. return self.rawNull
  216. }
  217. }
  218. set {
  219. error = nil
  220. switch unwrap(newValue) {
  221. case let number as NSNumber:
  222. if number.isBool {
  223. type = .bool
  224. self.rawBool = number.boolValue
  225. } else {
  226. type = .number
  227. self.rawNumber = number
  228. }
  229. case let string as String:
  230. type = .string
  231. self.rawString = string
  232. case _ as NSNull:
  233. type = .null
  234. case nil:
  235. type = .null
  236. case let array as [Any]:
  237. type = .array
  238. self.rawArray = array
  239. case let dictionary as [String: Any]:
  240. type = .dictionary
  241. self.rawDictionary = dictionary
  242. default:
  243. type = .unknown
  244. error = SwiftyJSONError.unsupportedType
  245. }
  246. }
  247. }
  248. /// The static null JSON
  249. @available(*, unavailable, renamed:"null")
  250. public static var nullJSON: JSON { return null }
  251. public static var null: JSON { return JSON(NSNull()) }
  252. }
  253. /// Private method to unwarp an object recursively
  254. private func unwrap(_ object: Any) -> Any {
  255. switch object {
  256. case let json as JSON:
  257. return unwrap(json.object)
  258. case let array as [Any]:
  259. return array.map(unwrap)
  260. case let dictionary as [String: Any]:
  261. var unwrappedDic = dictionary
  262. for (k, v) in dictionary {
  263. unwrappedDic[k] = unwrap(v)
  264. }
  265. return unwrappedDic
  266. default:
  267. return object
  268. }
  269. }
  270. public enum Index<T: Any>: Comparable {
  271. case array(Int)
  272. case dictionary(DictionaryIndex<String, T>)
  273. case null
  274. static public func == (lhs: Index, rhs: Index) -> Bool {
  275. switch (lhs, rhs) {
  276. case (.array(let left), .array(let right)):
  277. return left == right
  278. case (.dictionary(let left), .dictionary(let right)):
  279. return left == right
  280. case (.null, .null): return true
  281. default:
  282. return false
  283. }
  284. }
  285. static public func < (lhs: Index, rhs: Index) -> Bool {
  286. switch (lhs, rhs) {
  287. case (.array(let left), .array(let right)):
  288. return left < right
  289. case (.dictionary(let left), .dictionary(let right)):
  290. return left < right
  291. default:
  292. return false
  293. }
  294. }
  295. }
  296. public typealias JSONIndex = Index<JSON>
  297. public typealias JSONRawIndex = Index<Any>
  298. extension JSON: Swift.Collection {
  299. public typealias Index = JSONRawIndex
  300. public var startIndex: Index {
  301. switch type {
  302. case .array:
  303. return .array(rawArray.startIndex)
  304. case .dictionary:
  305. return .dictionary(rawDictionary.startIndex)
  306. default:
  307. return .null
  308. }
  309. }
  310. public var endIndex: Index {
  311. switch type {
  312. case .array:
  313. return .array(rawArray.endIndex)
  314. case .dictionary:
  315. return .dictionary(rawDictionary.endIndex)
  316. default:
  317. return .null
  318. }
  319. }
  320. public func index(after i: Index) -> Index {
  321. switch i {
  322. case .array(let idx):
  323. return .array(rawArray.index(after: idx))
  324. case .dictionary(let idx):
  325. return .dictionary(rawDictionary.index(after: idx))
  326. default:
  327. return .null
  328. }
  329. }
  330. public subscript (position: Index) -> (String, JSON) {
  331. switch position {
  332. case .array(let idx):
  333. return (String(idx), JSON(self.rawArray[idx]))
  334. case .dictionary(let idx):
  335. let (key, value) = self.rawDictionary[idx]
  336. return (key, JSON(value))
  337. default:
  338. return ("", JSON.null)
  339. }
  340. }
  341. }
  342. // MARK: - Subscript
  343. /**
  344. * To mark both String and Int can be used in subscript.
  345. */
  346. public enum JSONKey {
  347. case index(Int)
  348. case key(String)
  349. }
  350. public protocol JSONSubscriptType {
  351. var jsonKey: JSONKey { get }
  352. }
  353. extension Int: JSONSubscriptType {
  354. public var jsonKey: JSONKey {
  355. return JSONKey.index(self)
  356. }
  357. }
  358. extension String: JSONSubscriptType {
  359. public var jsonKey: JSONKey {
  360. return JSONKey.key(self)
  361. }
  362. }
  363. extension JSON {
  364. /// If `type` is `.array`, return json whose object is `array[index]`, otherwise return null json with error.
  365. fileprivate subscript(index index: Int) -> JSON {
  366. get {
  367. if self.type != .array {
  368. var r = JSON.null
  369. r.error = self.error ?? SwiftyJSONError.wrongType
  370. return r
  371. } else if self.rawArray.indices.contains(index) {
  372. return JSON(self.rawArray[index])
  373. } else {
  374. var r = JSON.null
  375. r.error = SwiftyJSONError.indexOutOfBounds
  376. return r
  377. }
  378. }
  379. set {
  380. if self.type == .array &&
  381. self.rawArray.indices.contains(index) &&
  382. newValue.error == nil {
  383. self.rawArray[index] = newValue.object
  384. }
  385. }
  386. }
  387. /// If `type` is `.dictionary`, return json whose object is `dictionary[key]` , otherwise return null json with error.
  388. fileprivate subscript(key key: String) -> JSON {
  389. get {
  390. var r = JSON.null
  391. if self.type == .dictionary {
  392. if let o = self.rawDictionary[key] {
  393. r = JSON(o)
  394. } else {
  395. r.error = SwiftyJSONError.notExist
  396. }
  397. } else {
  398. r.error = self.error ?? SwiftyJSONError.wrongType
  399. }
  400. return r
  401. }
  402. set {
  403. if self.type == .dictionary && newValue.error == nil {
  404. self.rawDictionary[key] = newValue.object
  405. }
  406. }
  407. }
  408. /// If `sub` is `Int`, return `subscript(index:)`; If `sub` is `String`, return `subscript(key:)`.
  409. fileprivate subscript(sub sub: JSONSubscriptType) -> JSON {
  410. get {
  411. switch sub.jsonKey {
  412. case .index(let index): return self[index: index]
  413. case .key(let key): return self[key: key]
  414. }
  415. }
  416. set {
  417. switch sub.jsonKey {
  418. case .index(let index): self[index: index] = newValue
  419. case .key(let key): self[key: key] = newValue
  420. }
  421. }
  422. }
  423. /**
  424. Find a json in the complex data structures by using array of Int and/or String as path.
  425. Example:
  426. ```
  427. let json = JSON[data]
  428. let path = [9,"list","person","name"]
  429. let name = json[path]
  430. ```
  431. The same as: let name = json[9]["list"]["person"]["name"]
  432. - parameter path: The target json's path.
  433. - returns: Return a json found by the path or a null json with error
  434. */
  435. public subscript(path: [JSONSubscriptType]) -> JSON {
  436. get {
  437. return path.reduce(self) { $0[sub: $1] }
  438. }
  439. set {
  440. switch path.count {
  441. case 0:
  442. return
  443. case 1:
  444. self[sub:path[0]].object = newValue.object
  445. default:
  446. var aPath = path
  447. aPath.remove(at: 0)
  448. var nextJSON = self[sub: path[0]]
  449. nextJSON[aPath] = newValue
  450. self[sub: path[0]] = nextJSON
  451. }
  452. }
  453. }
  454. /**
  455. Find a json in the complex data structures by using array of Int and/or String as path.
  456. - parameter path: The target json's path. Example:
  457. let name = json[9,"list","person","name"]
  458. The same as: let name = json[9]["list"]["person"]["name"]
  459. - returns: Return a json found by the path or a null json with error
  460. */
  461. public subscript(path: JSONSubscriptType...) -> JSON {
  462. get {
  463. return self[path]
  464. }
  465. set {
  466. self[path] = newValue
  467. }
  468. }
  469. }
  470. // MARK: - LiteralConvertible
  471. extension JSON: Swift.ExpressibleByStringLiteral {
  472. public init(stringLiteral value: StringLiteralType) {
  473. self.init(value)
  474. }
  475. public init(extendedGraphemeClusterLiteral value: StringLiteralType) {
  476. self.init(value)
  477. }
  478. public init(unicodeScalarLiteral value: StringLiteralType) {
  479. self.init(value)
  480. }
  481. }
  482. extension JSON: Swift.ExpressibleByIntegerLiteral {
  483. public init(integerLiteral value: IntegerLiteralType) {
  484. self.init(value)
  485. }
  486. }
  487. extension JSON: Swift.ExpressibleByBooleanLiteral {
  488. public init(booleanLiteral value: BooleanLiteralType) {
  489. self.init(value)
  490. }
  491. }
  492. extension JSON: Swift.ExpressibleByFloatLiteral {
  493. public init(floatLiteral value: FloatLiteralType) {
  494. self.init(value)
  495. }
  496. }
  497. extension JSON: Swift.ExpressibleByDictionaryLiteral {
  498. public init(dictionaryLiteral elements: (String, Any)...) {
  499. let dictionary = elements.reduce(into: [String: Any](), { $0[$1.0] = $1.1})
  500. self.init(dictionary)
  501. }
  502. }
  503. extension JSON: Swift.ExpressibleByArrayLiteral {
  504. public init(arrayLiteral elements: Any...) {
  505. self.init(elements)
  506. }
  507. }
  508. extension JSON: Swift.ExpressibleByNilLiteral {
  509. @available(*, deprecated, message: "use JSON.null instead. Will be removed in future versions")
  510. public init(nilLiteral: ()) {
  511. self.init(NSNull() as Any)
  512. }
  513. }
  514. // MARK: - Raw
  515. extension JSON: Swift.RawRepresentable {
  516. public init?(rawValue: Any) {
  517. if JSON(rawValue).type == .unknown {
  518. return nil
  519. } else {
  520. self.init(rawValue)
  521. }
  522. }
  523. public var rawValue: Any {
  524. return self.object
  525. }
  526. public func rawData(options opt: JSONSerialization.WritingOptions = JSONSerialization.WritingOptions(rawValue: 0)) throws -> Data {
  527. guard JSONSerialization.isValidJSONObject(self.object) else {
  528. throw SwiftyJSONError.invalidJSON
  529. }
  530. return try JSONSerialization.data(withJSONObject: self.object, options: opt)
  531. }
  532. public func rawString(_ encoding: String.Encoding = .utf8, options opt: JSONSerialization.WritingOptions = .prettyPrinted) -> String? {
  533. do {
  534. return try _rawString(encoding, options: [.jsonSerialization: opt])
  535. } catch {
  536. print("Could not serialize object to JSON because:", error.localizedDescription)
  537. return nil
  538. }
  539. }
  540. public func rawString(_ options: [writingOptionsKeys: Any]) -> String? {
  541. let encoding = options[.encoding] as? String.Encoding ?? String.Encoding.utf8
  542. let maxObjectDepth = options[.maxObjextDepth] as? Int ?? 10
  543. do {
  544. return try _rawString(encoding, options: options, maxObjectDepth: maxObjectDepth)
  545. } catch {
  546. print("Could not serialize object to JSON because:", error.localizedDescription)
  547. return nil
  548. }
  549. }
  550. fileprivate func _rawString(_ encoding: String.Encoding = .utf8, options: [writingOptionsKeys: Any], maxObjectDepth: Int = 10) throws -> String? {
  551. guard maxObjectDepth > 0 else { throw SwiftyJSONError.invalidJSON }
  552. switch self.type {
  553. case .dictionary:
  554. do {
  555. if !(options[.castNilToNSNull] as? Bool ?? false) {
  556. let jsonOption = options[.jsonSerialization] as? JSONSerialization.WritingOptions ?? JSONSerialization.WritingOptions.prettyPrinted
  557. let data = try self.rawData(options: jsonOption)
  558. return String(data: data, encoding: encoding)
  559. }
  560. guard let dict = self.object as? [String: Any?] else {
  561. return nil
  562. }
  563. let body = try dict.keys.map { key throws -> String in
  564. guard let value = dict[key] else {
  565. return "\"\(key)\": null"
  566. }
  567. guard let unwrappedValue = value else {
  568. return "\"\(key)\": null"
  569. }
  570. let nestedValue = JSON(unwrappedValue)
  571. guard let nestedString = try nestedValue._rawString(encoding, options: options, maxObjectDepth: maxObjectDepth - 1) else {
  572. throw SwiftyJSONError.elementTooDeep
  573. }
  574. if nestedValue.type == .string {
  575. return "\"\(key)\": \"\(nestedString.replacingOccurrences(of: "\\", with: "\\\\").replacingOccurrences(of: "\"", with: "\\\""))\""
  576. } else {
  577. return "\"\(key)\": \(nestedString)"
  578. }
  579. }
  580. return "{\(body.joined(separator: ","))}"
  581. } catch _ {
  582. return nil
  583. }
  584. case .array:
  585. do {
  586. if !(options[.castNilToNSNull] as? Bool ?? false) {
  587. let jsonOption = options[.jsonSerialization] as? JSONSerialization.WritingOptions ?? JSONSerialization.WritingOptions.prettyPrinted
  588. let data = try self.rawData(options: jsonOption)
  589. return String(data: data, encoding: encoding)
  590. }
  591. guard let array = self.object as? [Any?] else {
  592. return nil
  593. }
  594. let body = try array.map { value throws -> String in
  595. guard let unwrappedValue = value else {
  596. return "null"
  597. }
  598. let nestedValue = JSON(unwrappedValue)
  599. guard let nestedString = try nestedValue._rawString(encoding, options: options, maxObjectDepth: maxObjectDepth - 1) else {
  600. throw SwiftyJSONError.invalidJSON
  601. }
  602. if nestedValue.type == .string {
  603. return "\"\(nestedString.replacingOccurrences(of: "\\", with: "\\\\").replacingOccurrences(of: "\"", with: "\\\""))\""
  604. } else {
  605. return nestedString
  606. }
  607. }
  608. return "[\(body.joined(separator: ","))]"
  609. } catch _ {
  610. return nil
  611. }
  612. case .string:
  613. return self.rawString
  614. case .number:
  615. return self.rawNumber.stringValue
  616. case .bool:
  617. return self.rawBool.description
  618. case .null:
  619. return "null"
  620. default:
  621. return nil
  622. }
  623. }
  624. }
  625. // MARK: - Printable, DebugPrintable
  626. extension JSON: Swift.CustomStringConvertible, Swift.CustomDebugStringConvertible {
  627. public var description: String {
  628. if let string = self.rawString(options: .prettyPrinted) {
  629. return string
  630. } else {
  631. return "unknown"
  632. }
  633. }
  634. public var debugDescription: String {
  635. return description
  636. }
  637. }
  638. // MARK: - Array
  639. extension JSON {
  640. //Optional [JSON]
  641. public var array: [JSON]? {
  642. if self.type == .array {
  643. return self.rawArray.map { JSON($0) }
  644. } else {
  645. return nil
  646. }
  647. }
  648. //Non-optional [JSON]
  649. public var arrayValue: [JSON] {
  650. return self.array ?? []
  651. }
  652. //Optional [Any]
  653. public var arrayObject: [Any]? {
  654. get {
  655. switch self.type {
  656. case .array:
  657. return self.rawArray
  658. default:
  659. return nil
  660. }
  661. }
  662. set {
  663. if let array = newValue {
  664. self.object = array
  665. } else {
  666. self.object = NSNull()
  667. }
  668. }
  669. }
  670. }
  671. // MARK: - Dictionary
  672. extension JSON {
  673. //Optional [String : JSON]
  674. public var dictionary: [String: JSON]? {
  675. if self.type == .dictionary {
  676. var d = [String: JSON](minimumCapacity: rawDictionary.count)
  677. for (key, value) in rawDictionary {
  678. d[key] = JSON(value)
  679. }
  680. return d
  681. } else {
  682. return nil
  683. }
  684. }
  685. //Non-optional [String : JSON]
  686. public var dictionaryValue: [String: JSON] {
  687. return self.dictionary ?? [:]
  688. }
  689. //Optional [String : Any]
  690. public var dictionaryObject: [String: Any]? {
  691. get {
  692. switch self.type {
  693. case .dictionary:
  694. return self.rawDictionary
  695. default:
  696. return nil
  697. }
  698. }
  699. set {
  700. if let v = newValue {
  701. self.object = v
  702. } else {
  703. self.object = NSNull()
  704. }
  705. }
  706. }
  707. }
  708. // MARK: - Bool
  709. extension JSON { // : Swift.Bool
  710. //Optional bool
  711. public var bool: Bool? {
  712. get {
  713. switch self.type {
  714. case .bool:
  715. return self.rawBool
  716. default:
  717. return nil
  718. }
  719. }
  720. set {
  721. if let newValue = newValue {
  722. self.object = newValue as Bool
  723. } else {
  724. self.object = NSNull()
  725. }
  726. }
  727. }
  728. //Non-optional bool
  729. public var boolValue: Bool {
  730. get {
  731. switch self.type {
  732. case .bool:
  733. return self.rawBool
  734. case .number:
  735. return self.rawNumber.boolValue
  736. case .string:
  737. return ["true", "y", "t", "yes", "1"].contains { self.rawString.caseInsensitiveCompare($0) == .orderedSame }
  738. default:
  739. return false
  740. }
  741. }
  742. set {
  743. self.object = newValue
  744. }
  745. }
  746. }
  747. // MARK: - String
  748. extension JSON {
  749. //Optional string
  750. public var string: String? {
  751. get {
  752. switch self.type {
  753. case .string:
  754. return self.object as? String
  755. default:
  756. return nil
  757. }
  758. }
  759. set {
  760. if let newValue = newValue {
  761. self.object = NSString(string: newValue)
  762. } else {
  763. self.object = NSNull()
  764. }
  765. }
  766. }
  767. //Non-optional string
  768. public var stringValue: String {
  769. get {
  770. switch self.type {
  771. case .string:
  772. return self.object as? String ?? ""
  773. case .number:
  774. return self.rawNumber.stringValue
  775. case .bool:
  776. return (self.object as? Bool).map { String($0) } ?? ""
  777. default:
  778. return ""
  779. }
  780. }
  781. set {
  782. self.object = NSString(string: newValue)
  783. }
  784. }
  785. }
  786. // MARK: - Number
  787. extension JSON {
  788. //Optional number
  789. public var number: NSNumber? {
  790. get {
  791. switch self.type {
  792. case .number:
  793. return self.rawNumber
  794. case .bool:
  795. return NSNumber(value: self.rawBool ? 1 : 0)
  796. default:
  797. return nil
  798. }
  799. }
  800. set {
  801. self.object = newValue ?? NSNull()
  802. }
  803. }
  804. //Non-optional number
  805. public var numberValue: NSNumber {
  806. get {
  807. switch self.type {
  808. case .string:
  809. let decimal = NSDecimalNumber(string: self.object as? String)
  810. if decimal == NSDecimalNumber.notANumber { // indicates parse error
  811. return NSDecimalNumber.zero
  812. }
  813. return decimal
  814. case .number:
  815. return self.object as? NSNumber ?? NSNumber(value: 0)
  816. case .bool:
  817. return NSNumber(value: self.rawBool ? 1 : 0)
  818. default:
  819. return NSNumber(value: 0.0)
  820. }
  821. }
  822. set {
  823. self.object = newValue
  824. }
  825. }
  826. }
  827. // MARK: - Null
  828. extension JSON {
  829. public var null: NSNull? {
  830. get {
  831. switch self.type {
  832. case .null:
  833. return self.rawNull
  834. default:
  835. return nil
  836. }
  837. }
  838. set {
  839. self.object = NSNull()
  840. }
  841. }
  842. public func exists() -> Bool {
  843. if let errorValue = error, (400...1000).contains(errorValue.errorCode) {
  844. return false
  845. }
  846. return true
  847. }
  848. }
  849. // MARK: - URL
  850. extension JSON {
  851. //Optional URL
  852. public var url: URL? {
  853. get {
  854. switch self.type {
  855. case .string:
  856. // Check for existing percent escapes first to prevent double-escaping of % character
  857. if self.rawString.range(of: "%[0-9A-Fa-f]{2}", options: .regularExpression, range: nil, locale: nil) != nil {
  858. return Foundation.URL(string: self.rawString)
  859. } else if let encodedString_ = self.rawString.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryAllowed) {
  860. // We have to use `Foundation.URL` otherwise it conflicts with the variable name.
  861. return Foundation.URL(string: encodedString_)
  862. } else {
  863. return nil
  864. }
  865. default:
  866. return nil
  867. }
  868. }
  869. set {
  870. self.object = newValue?.absoluteString ?? NSNull()
  871. }
  872. }
  873. }
  874. // MARK: - Int, Double, Float, Int8, Int16, Int32, Int64
  875. extension JSON {
  876. public var double: Double? {
  877. get {
  878. return self.number?.doubleValue
  879. }
  880. set {
  881. if let newValue = newValue {
  882. self.object = NSNumber(value: newValue)
  883. } else {
  884. self.object = NSNull()
  885. }
  886. }
  887. }
  888. public var doubleValue: Double {
  889. get {
  890. return self.numberValue.doubleValue
  891. }
  892. set {
  893. self.object = NSNumber(value: newValue)
  894. }
  895. }
  896. public var float: Float? {
  897. get {
  898. return self.number?.floatValue
  899. }
  900. set {
  901. if let newValue = newValue {
  902. self.object = NSNumber(value: newValue)
  903. } else {
  904. self.object = NSNull()
  905. }
  906. }
  907. }
  908. public var floatValue: Float {
  909. get {
  910. return self.numberValue.floatValue
  911. }
  912. set {
  913. self.object = NSNumber(value: newValue)
  914. }
  915. }
  916. public var int: Int? {
  917. get {
  918. return self.number?.intValue
  919. }
  920. set {
  921. if let newValue = newValue {
  922. self.object = NSNumber(value: newValue)
  923. } else {
  924. self.object = NSNull()
  925. }
  926. }
  927. }
  928. public var intValue: Int {
  929. get {
  930. return self.numberValue.intValue
  931. }
  932. set {
  933. self.object = NSNumber(value: newValue)
  934. }
  935. }
  936. public var uInt: UInt? {
  937. get {
  938. return self.number?.uintValue
  939. }
  940. set {
  941. if let newValue = newValue {
  942. self.object = NSNumber(value: newValue)
  943. } else {
  944. self.object = NSNull()
  945. }
  946. }
  947. }
  948. public var uIntValue: UInt {
  949. get {
  950. return self.numberValue.uintValue
  951. }
  952. set {
  953. self.object = NSNumber(value: newValue)
  954. }
  955. }
  956. public var int8: Int8? {
  957. get {
  958. return self.number?.int8Value
  959. }
  960. set {
  961. if let newValue = newValue {
  962. self.object = NSNumber(value: Int(newValue))
  963. } else {
  964. self.object = NSNull()
  965. }
  966. }
  967. }
  968. public var int8Value: Int8 {
  969. get {
  970. return self.numberValue.int8Value
  971. }
  972. set {
  973. self.object = NSNumber(value: Int(newValue))
  974. }
  975. }
  976. public var uInt8: UInt8? {
  977. get {
  978. return self.number?.uint8Value
  979. }
  980. set {
  981. if let newValue = newValue {
  982. self.object = NSNumber(value: newValue)
  983. } else {
  984. self.object = NSNull()
  985. }
  986. }
  987. }
  988. public var uInt8Value: UInt8 {
  989. get {
  990. return self.numberValue.uint8Value
  991. }
  992. set {
  993. self.object = NSNumber(value: newValue)
  994. }
  995. }
  996. public var int16: Int16? {
  997. get {
  998. return self.number?.int16Value
  999. }
  1000. set {
  1001. if let newValue = newValue {
  1002. self.object = NSNumber(value: newValue)
  1003. } else {
  1004. self.object = NSNull()
  1005. }
  1006. }
  1007. }
  1008. public var int16Value: Int16 {
  1009. get {
  1010. return self.numberValue.int16Value
  1011. }
  1012. set {
  1013. self.object = NSNumber(value: newValue)
  1014. }
  1015. }
  1016. public var uInt16: UInt16? {
  1017. get {
  1018. return self.number?.uint16Value
  1019. }
  1020. set {
  1021. if let newValue = newValue {
  1022. self.object = NSNumber(value: newValue)
  1023. } else {
  1024. self.object = NSNull()
  1025. }
  1026. }
  1027. }
  1028. public var uInt16Value: UInt16 {
  1029. get {
  1030. return self.numberValue.uint16Value
  1031. }
  1032. set {
  1033. self.object = NSNumber(value: newValue)
  1034. }
  1035. }
  1036. public var int32: Int32? {
  1037. get {
  1038. return self.number?.int32Value
  1039. }
  1040. set {
  1041. if let newValue = newValue {
  1042. self.object = NSNumber(value: newValue)
  1043. } else {
  1044. self.object = NSNull()
  1045. }
  1046. }
  1047. }
  1048. public var int32Value: Int32 {
  1049. get {
  1050. return self.numberValue.int32Value
  1051. }
  1052. set {
  1053. self.object = NSNumber(value: newValue)
  1054. }
  1055. }
  1056. public var uInt32: UInt32? {
  1057. get {
  1058. return self.number?.uint32Value
  1059. }
  1060. set {
  1061. if let newValue = newValue {
  1062. self.object = NSNumber(value: newValue)
  1063. } else {
  1064. self.object = NSNull()
  1065. }
  1066. }
  1067. }
  1068. public var uInt32Value: UInt32 {
  1069. get {
  1070. return self.numberValue.uint32Value
  1071. }
  1072. set {
  1073. self.object = NSNumber(value: newValue)
  1074. }
  1075. }
  1076. public var int64: Int64? {
  1077. get {
  1078. return self.number?.int64Value
  1079. }
  1080. set {
  1081. if let newValue = newValue {
  1082. self.object = NSNumber(value: newValue)
  1083. } else {
  1084. self.object = NSNull()
  1085. }
  1086. }
  1087. }
  1088. public var int64Value: Int64 {
  1089. get {
  1090. return self.numberValue.int64Value
  1091. }
  1092. set {
  1093. self.object = NSNumber(value: newValue)
  1094. }
  1095. }
  1096. public var uInt64: UInt64? {
  1097. get {
  1098. return self.number?.uint64Value
  1099. }
  1100. set {
  1101. if let newValue = newValue {
  1102. self.object = NSNumber(value: newValue)
  1103. } else {
  1104. self.object = NSNull()
  1105. }
  1106. }
  1107. }
  1108. public var uInt64Value: UInt64 {
  1109. get {
  1110. return self.numberValue.uint64Value
  1111. }
  1112. set {
  1113. self.object = NSNumber(value: newValue)
  1114. }
  1115. }
  1116. }
  1117. // MARK: - Comparable
  1118. extension JSON: Swift.Comparable {}
  1119. public func == (lhs: JSON, rhs: JSON) -> Bool {
  1120. switch (lhs.type, rhs.type) {
  1121. case (.number, .number):
  1122. return lhs.rawNumber == rhs.rawNumber
  1123. case (.string, .string):
  1124. return lhs.rawString == rhs.rawString
  1125. case (.bool, .bool):
  1126. return lhs.rawBool == rhs.rawBool
  1127. case (.array, .array):
  1128. return lhs.rawArray as NSArray == rhs.rawArray as NSArray
  1129. case (.dictionary, .dictionary):
  1130. return lhs.rawDictionary as NSDictionary == rhs.rawDictionary as NSDictionary
  1131. case (.null, .null):
  1132. return true
  1133. default:
  1134. return false
  1135. }
  1136. }
  1137. public func <= (lhs: JSON, rhs: JSON) -> Bool {
  1138. switch (lhs.type, rhs.type) {
  1139. case (.number, .number):
  1140. return lhs.rawNumber <= rhs.rawNumber
  1141. case (.string, .string):
  1142. return lhs.rawString <= rhs.rawString
  1143. case (.bool, .bool):
  1144. return lhs.rawBool == rhs.rawBool
  1145. case (.array, .array):
  1146. return lhs.rawArray as NSArray == rhs.rawArray as NSArray
  1147. case (.dictionary, .dictionary):
  1148. return lhs.rawDictionary as NSDictionary == rhs.rawDictionary as NSDictionary
  1149. case (.null, .null):
  1150. return true
  1151. default:
  1152. return false
  1153. }
  1154. }
  1155. public func >= (lhs: JSON, rhs: JSON) -> Bool {
  1156. switch (lhs.type, rhs.type) {
  1157. case (.number, .number):
  1158. return lhs.rawNumber >= rhs.rawNumber
  1159. case (.string, .string):
  1160. return lhs.rawString >= rhs.rawString
  1161. case (.bool, .bool):
  1162. return lhs.rawBool == rhs.rawBool
  1163. case (.array, .array):
  1164. return lhs.rawArray as NSArray == rhs.rawArray as NSArray
  1165. case (.dictionary, .dictionary):
  1166. return lhs.rawDictionary as NSDictionary == rhs.rawDictionary as NSDictionary
  1167. case (.null, .null):
  1168. return true
  1169. default:
  1170. return false
  1171. }
  1172. }
  1173. public func > (lhs: JSON, rhs: JSON) -> Bool {
  1174. switch (lhs.type, rhs.type) {
  1175. case (.number, .number):
  1176. return lhs.rawNumber > rhs.rawNumber
  1177. case (.string, .string):
  1178. return lhs.rawString > rhs.rawString
  1179. default:
  1180. return false
  1181. }
  1182. }
  1183. public func < (lhs: JSON, rhs: JSON) -> Bool {
  1184. switch (lhs.type, rhs.type) {
  1185. case (.number, .number):
  1186. return lhs.rawNumber < rhs.rawNumber
  1187. case (.string, .string):
  1188. return lhs.rawString < rhs.rawString
  1189. default:
  1190. return false
  1191. }
  1192. }
  1193. private let trueNumber = NSNumber(value: true)
  1194. private let falseNumber = NSNumber(value: false)
  1195. private let trueObjCType = String(cString: trueNumber.objCType)
  1196. private let falseObjCType = String(cString: falseNumber.objCType)
  1197. // MARK: - NSNumber: Comparable
  1198. extension NSNumber {
  1199. fileprivate var isBool: Bool {
  1200. let objCType = String(cString: self.objCType)
  1201. if (self.compare(trueNumber) == .orderedSame && objCType == trueObjCType) || (self.compare(falseNumber) == .orderedSame && objCType == falseObjCType) {
  1202. return true
  1203. } else {
  1204. return false
  1205. }
  1206. }
  1207. }
  1208. func == (lhs: NSNumber, rhs: NSNumber) -> Bool {
  1209. switch (lhs.isBool, rhs.isBool) {
  1210. case (false, true):
  1211. return false
  1212. case (true, false):
  1213. return false
  1214. default:
  1215. return lhs.compare(rhs) == .orderedSame
  1216. }
  1217. }
  1218. func != (lhs: NSNumber, rhs: NSNumber) -> Bool {
  1219. return !(lhs == rhs)
  1220. }
  1221. func < (lhs: NSNumber, rhs: NSNumber) -> Bool {
  1222. switch (lhs.isBool, rhs.isBool) {
  1223. case (false, true):
  1224. return false
  1225. case (true, false):
  1226. return false
  1227. default:
  1228. return lhs.compare(rhs) == .orderedAscending
  1229. }
  1230. }
  1231. func > (lhs: NSNumber, rhs: NSNumber) -> Bool {
  1232. switch (lhs.isBool, rhs.isBool) {
  1233. case (false, true):
  1234. return false
  1235. case (true, false):
  1236. return false
  1237. default:
  1238. return lhs.compare(rhs) == ComparisonResult.orderedDescending
  1239. }
  1240. }
  1241. func <= (lhs: NSNumber, rhs: NSNumber) -> Bool {
  1242. switch (lhs.isBool, rhs.isBool) {
  1243. case (false, true):
  1244. return false
  1245. case (true, false):
  1246. return false
  1247. default:
  1248. return lhs.compare(rhs) != .orderedDescending
  1249. }
  1250. }
  1251. func >= (lhs: NSNumber, rhs: NSNumber) -> Bool {
  1252. switch (lhs.isBool, rhs.isBool) {
  1253. case (false, true):
  1254. return false
  1255. case (true, false):
  1256. return false
  1257. default:
  1258. return lhs.compare(rhs) != .orderedAscending
  1259. }
  1260. }
  1261. public enum writingOptionsKeys {
  1262. case jsonSerialization
  1263. case castNilToNSNull
  1264. case maxObjextDepth
  1265. case encoding
  1266. }
  1267. // MARK: - JSON: Codable
  1268. extension JSON: Codable {
  1269. private static var codableTypes: [Codable.Type] {
  1270. return [
  1271. Bool.self,
  1272. Int.self,
  1273. Int8.self,
  1274. Int16.self,
  1275. Int32.self,
  1276. Int64.self,
  1277. UInt.self,
  1278. UInt8.self,
  1279. UInt16.self,
  1280. UInt32.self,
  1281. UInt64.self,
  1282. Double.self,
  1283. String.self,
  1284. [JSON].self,
  1285. [String: JSON].self
  1286. ]
  1287. }
  1288. public init(from decoder: Decoder) throws {
  1289. var object: Any?
  1290. if let container = try? decoder.singleValueContainer(), !container.decodeNil() {
  1291. for type in JSON.codableTypes {
  1292. if object != nil {
  1293. break
  1294. }
  1295. // try to decode value
  1296. switch type {
  1297. case let boolType as Bool.Type:
  1298. object = try? container.decode(boolType)
  1299. case let intType as Int.Type:
  1300. object = try? container.decode(intType)
  1301. case let int8Type as Int8.Type:
  1302. object = try? container.decode(int8Type)
  1303. case let int32Type as Int32.Type:
  1304. object = try? container.decode(int32Type)
  1305. case let int64Type as Int64.Type:
  1306. object = try? container.decode(int64Type)
  1307. case let uintType as UInt.Type:
  1308. object = try? container.decode(uintType)
  1309. case let uint8Type as UInt8.Type:
  1310. object = try? container.decode(uint8Type)
  1311. case let uint16Type as UInt16.Type:
  1312. object = try? container.decode(uint16Type)
  1313. case let uint32Type as UInt32.Type:
  1314. object = try? container.decode(uint32Type)
  1315. case let uint64Type as UInt64.Type:
  1316. object = try? container.decode(uint64Type)
  1317. case let doubleType as Double.Type:
  1318. object = try? container.decode(doubleType)
  1319. case let stringType as String.Type:
  1320. object = try? container.decode(stringType)
  1321. case let jsonValueArrayType as [JSON].Type:
  1322. object = try? container.decode(jsonValueArrayType)
  1323. case let jsonValueDictType as [String: JSON].Type:
  1324. object = try? container.decode(jsonValueDictType)
  1325. default:
  1326. break
  1327. }
  1328. }
  1329. }
  1330. self.init(object ?? NSNull())
  1331. }
  1332. public func encode(to encoder: Encoder) throws {
  1333. var container = encoder.singleValueContainer()
  1334. if object is NSNull {
  1335. try container.encodeNil()
  1336. return
  1337. }
  1338. switch object {
  1339. case let intValue as Int:
  1340. try container.encode(intValue)
  1341. case let int8Value as Int8:
  1342. try container.encode(int8Value)
  1343. case let int32Value as Int32:
  1344. try container.encode(int32Value)
  1345. case let int64Value as Int64:
  1346. try container.encode(int64Value)
  1347. case let uintValue as UInt:
  1348. try container.encode(uintValue)
  1349. case let uint8Value as UInt8:
  1350. try container.encode(uint8Value)
  1351. case let uint16Value as UInt16:
  1352. try container.encode(uint16Value)
  1353. case let uint32Value as UInt32:
  1354. try container.encode(uint32Value)
  1355. case let uint64Value as UInt64:
  1356. try container.encode(uint64Value)
  1357. case let doubleValue as Double:
  1358. try container.encode(doubleValue)
  1359. case let boolValue as Bool:
  1360. try container.encode(boolValue)
  1361. case let stringValue as String:
  1362. try container.encode(stringValue)
  1363. case is [Any]:
  1364. let jsonValueArray = array ?? []
  1365. try container.encode(jsonValueArray)
  1366. case is [String: Any]:
  1367. let jsonValueDictValue = dictionary ?? [:]
  1368. try container.encode(jsonValueDictValue)
  1369. default:
  1370. break
  1371. }
  1372. }
  1373. }