Project Setup

This commit is contained in:
manaknightdev
2023-03-13 23:20:27 +05:30
commit d4da2b5e02
178 changed files with 29139 additions and 0 deletions
+73
View File
@@ -0,0 +1,73 @@
//
// CodableTransform.swift
// ObjectMapper
//
// Created by Jari Kalinainen on 10/10/2018.
//
// The MIT License (MIT)
//
// Copyright (c) 2014-2018 Tristan Himmelman
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
import Foundation
/// Transforms JSON dictionary to Codable type T and back
open class CodableTransform<T: Codable>: TransformType {
public typealias Object = T
public typealias JSON = Any
public init() {}
open func transformFromJSON(_ value: Any?) -> Object? {
var _data: Data? = nil
switch value {
case let dict as [String : Any]:
_data = try? JSONSerialization.data(withJSONObject: dict, options: [])
case let array as [[String : Any]]:
_data = try? JSONSerialization.data(withJSONObject: array, options: [])
default:
_data = nil
}
guard let data = _data else { return nil }
do {
let decoder = JSONDecoder()
let item = try decoder.decode(T.self, from: data)
return item
} catch {
return nil
}
}
open func transformToJSON(_ value: T?) -> JSON? {
guard let item = value else {
return nil
}
do {
let encoder = JSONEncoder()
let data = try encoder.encode(item)
let dictionary = try JSONSerialization.jsonObject(with: data, options: .allowFragments)
return dictionary
} catch {
return nil
}
}
}
@@ -0,0 +1,40 @@
//
// CustomDateFormatTransform.swift
// ObjectMapper
//
// Created by Dan McCracken on 3/8/15.
//
// The MIT License (MIT)
//
// Copyright (c) 2014-2018 Tristan Himmelman
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
import Foundation
open class CustomDateFormatTransform: DateFormatterTransform {
public init(formatString: String) {
let formatter = DateFormatter()
formatter.locale = Locale(identifier: "en_US_POSIX")
formatter.dateFormat = formatString
super.init(dateFormatter: formatter)
}
}
+50
View File
@@ -0,0 +1,50 @@
//
// DataTransform.swift
// ObjectMapper
//
// Created by Yagrushkin, Evgeny on 8/30/16.
//
// The MIT License (MIT)
//
// Copyright (c) 2014-2018 Tristan Himmelman
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
import Foundation
open class DataTransform: TransformType {
public typealias Object = Data
public typealias JSON = String
public init() {}
open func transformFromJSON(_ value: Any?) -> Data? {
guard let string = value as? String else{
return nil
}
return Data(base64Encoded: string)
}
open func transformToJSON(_ value: Data?) -> String? {
guard let data = value else{
return nil
}
return data.base64EncodedString()
}
}
@@ -0,0 +1,54 @@
//
// DateFormatterTransform.swift
// ObjectMapper
//
// Created by Tristan Himmelman on 2015-03-09.
//
// The MIT License (MIT)
//
// Copyright (c) 2014-2018 Tristan Himmelman
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
import Foundation
open class DateFormatterTransform: TransformType {
public typealias Object = Date
public typealias JSON = String
public let dateFormatter: DateFormatter
public init(dateFormatter: DateFormatter) {
self.dateFormatter = dateFormatter
}
open func transformFromJSON(_ value: Any?) -> Date? {
if let dateString = value as? String {
return dateFormatter.date(from: dateString)
}
return nil
}
open func transformToJSON(_ value: Date?) -> String? {
if let date = value {
return dateFormatter.string(from: date)
}
return nil
}
}
+75
View File
@@ -0,0 +1,75 @@
//
// DateTransform.swift
// ObjectMapper
//
// Created by Tristan Himmelman on 2014-10-13.
//
// The MIT License (MIT)
//
// Copyright (c) 2014-2018 Tristan Himmelman
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
import Foundation
open class DateTransform: TransformType {
public typealias Object = Date
public typealias JSON = Double
public enum Unit: TimeInterval {
case seconds = 1
case milliseconds = 1_000
func addScale(to interval: TimeInterval) -> TimeInterval {
return interval * rawValue
}
func removeScale(from interval: TimeInterval) -> TimeInterval {
return interval / rawValue
}
}
private let unit: Unit
public init(unit: Unit = .seconds) {
self.unit = unit
}
open func transformFromJSON(_ value: Any?) -> Date? {
var timeInterval: TimeInterval?
if let timeInt = value as? Double {
timeInterval = TimeInterval(timeInt)
}
if let timeStr = value as? String {
timeInterval = TimeInterval(atof(timeStr))
}
return timeInterval.flatMap {
return Date(timeIntervalSince1970: unit.removeScale(from: $0))
}
}
open func transformToJSON(_ value: Date?) -> Double? {
if let date = value {
return Double(unit.addScale(to: date.timeIntervalSince1970))
}
return nil
}
}
@@ -0,0 +1,76 @@
//
// DictionaryTransform.swift
// ObjectMapper
//
// Created by Milen Halachev on 7/20/16.
//
// Copyright (c) 2014-2018 Tristan Himmelman
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
import Foundation
///Transforms [String: AnyObject] <-> [Key: Value] where Key is RawRepresentable as String, Value is Mappable
public struct DictionaryTransform<Key, Value>: TransformType where Key: Hashable, Key: RawRepresentable, Key.RawValue == String, Value: Mappable {
public init() {
}
public func transformFromJSON(_ value: Any?) -> [Key: Value]? {
guard let json = value as? [String: Any] else {
return nil
}
let result = json.reduce([:]) { (result, element) -> [Key: Value] in
guard
let key = Key(rawValue: element.0),
let valueJSON = element.1 as? [String: Any],
let value = Value(JSON: valueJSON)
else {
return result
}
var result = result
result[key] = value
return result
}
return result
}
public func transformToJSON(_ value: [Key: Value]?) -> Any? {
let result = value?.reduce([:]) { (result, element) -> [String: Any] in
let key = element.0.rawValue
let value = element.1.toJSON()
var result = result
result[key] = value
return result
}
return result
}
}
+120
View File
@@ -0,0 +1,120 @@
//
// EnumOperators.swift
// ObjectMapper
//
// Created by Tristan Himmelman on 2016-09-26.
//
// The MIT License (MIT)
//
// Copyright (c) 2014-2018 Tristan Himmelman
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
import Foundation
// MARK:- Raw Representable types
/// Object of Raw Representable type
public func <- <T: RawRepresentable>(left: inout T, right: Map) {
left <- (right, EnumTransform())
}
public func >>> <T: RawRepresentable>(left: T, right: Map) {
left >>> (right, EnumTransform())
}
/// Optional Object of Raw Representable type
public func <- <T: RawRepresentable>(left: inout T?, right: Map) {
left <- (right, EnumTransform())
}
public func >>> <T: RawRepresentable>(left: T?, right: Map) {
left >>> (right, EnumTransform())
}
// Code targeting the Swift 4.1 compiler and below.
#if !(swift(>=4.1.50) || (swift(>=3.4) && !swift(>=4.0)))
/// Implicitly Unwrapped Optional Object of Raw Representable type
public func <- <T: RawRepresentable>(left: inout T!, right: Map) {
left <- (right, EnumTransform())
}
#endif
// MARK:- Arrays of Raw Representable type
/// Array of Raw Representable object
public func <- <T: RawRepresentable>(left: inout [T], right: Map) {
left <- (right, EnumTransform())
}
public func >>> <T: RawRepresentable>(left: [T], right: Map) {
left >>> (right, EnumTransform())
}
/// Array of Raw Representable object
public func <- <T: RawRepresentable>(left: inout [T]?, right: Map) {
left <- (right, EnumTransform())
}
public func >>> <T: RawRepresentable>(left: [T]?, right: Map) {
left >>> (right, EnumTransform())
}
// Code targeting the Swift 4.1 compiler and below.
#if !(swift(>=4.1.50) || (swift(>=3.4) && !swift(>=4.0)))
/// Array of Raw Representable object
public func <- <T: RawRepresentable>(left: inout [T]!, right: Map) {
left <- (right, EnumTransform())
}
#endif
// MARK:- Dictionaries of Raw Representable type
/// Dictionary of Raw Representable object
public func <- <T: RawRepresentable>(left: inout [String: T], right: Map) {
left <- (right, EnumTransform())
}
public func >>> <T: RawRepresentable>(left: [String: T], right: Map) {
left >>> (right, EnumTransform())
}
/// Dictionary of Raw Representable object
public func <- <T: RawRepresentable>(left: inout [String: T]?, right: Map) {
left <- (right, EnumTransform())
}
public func >>> <T: RawRepresentable>(left: [String: T]?, right: Map) {
left >>> (right, EnumTransform())
}
// Code targeting the Swift 4.1 compiler and below.
#if !(swift(>=4.1.50) || (swift(>=3.4) && !swift(>=4.0)))
/// Dictionary of Raw Representable object
public func <- <T: RawRepresentable>(left: inout [String: T]!, right: Map) {
left <- (right, EnumTransform())
}
#endif
+50
View File
@@ -0,0 +1,50 @@
//
// EnumTransform.swift
// ObjectMapper
//
// Created by Kaan Dedeoglu on 3/20/15.
//
// The MIT License (MIT)
//
// Copyright (c) 2014-2018 Tristan Himmelman
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
import Foundation
open class EnumTransform<T: RawRepresentable>: TransformType {
public typealias Object = T
public typealias JSON = T.RawValue
public init() {}
open func transformFromJSON(_ value: Any?) -> T? {
if let raw = value as? T.RawValue {
return T(rawValue: raw)
}
return nil
}
open func transformToJSON(_ value: T?) -> T.RawValue? {
if let obj = value {
return obj.rawValue
}
return nil
}
}
+202
View File
@@ -0,0 +1,202 @@
//
// FromJSON.swift
// ObjectMapper
//
// Created by Tristan Himmelman on 2014-10-09.
//
// The MIT License (MIT)
//
// Copyright (c) 2014-2016 Tristan Himmelman
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
internal final class FromJSON {
/// Basic type
class func basicType<FieldType>(_ field: inout FieldType, object: FieldType?) {
if let value = object {
field = value
}
}
/// optional basic type
class func optionalBasicType<FieldType>(_ field: inout FieldType?, object: FieldType?) {
field = object
}
// Code targeting the Swift 4.1 compiler and below.
#if !(swift(>=4.1.50) || (swift(>=3.4) && !swift(>=4.0)))
/// Implicitly unwrapped optional basic type
class func optionalBasicType<FieldType>(_ field: inout FieldType!, object: FieldType?) {
field = object
}
#endif
/// Mappable object
class func object<N: BaseMappable>(_ field: inout N, map: Map) {
if map.toObject {
field = Mapper(context: map.context).map(JSONObject: map.currentValue, toObject: field)
} else if let value: N = Mapper(context: map.context).map(JSONObject: map.currentValue) {
field = value
}
}
/// Optional Mappable Object
class func optionalObject<N: BaseMappable>(_ field: inout N?, map: Map) {
if let f = field , map.toObject && map.currentValue != nil {
field = Mapper(context: map.context).map(JSONObject: map.currentValue, toObject: f)
} else {
field = Mapper(context: map.context).map(JSONObject: map.currentValue)
}
}
// Code targeting the Swift 4.1 compiler and below.
#if !(swift(>=4.1.50) || (swift(>=3.4) && !swift(>=4.0)))
/// Implicitly unwrapped Optional Mappable Object
class func optionalObject<N: BaseMappable>(_ field: inout N!, map: Map) {
if let f = field , map.toObject && map.currentValue != nil {
field = Mapper(context: map.context).map(JSONObject: map.currentValue, toObject: f)
} else {
field = Mapper(context: map.context).map(JSONObject: map.currentValue)
}
}
#endif
/// mappable object array
class func objectArray<N: BaseMappable>(_ field: inout Array<N>, map: Map) {
if let objects = Mapper<N>(context: map.context).mapArray(JSONObject: map.currentValue) {
field = objects
}
}
/// optional mappable object array
class func optionalObjectArray<N: BaseMappable>(_ field: inout Array<N>?, map: Map) {
if let objects: Array<N> = Mapper(context: map.context).mapArray(JSONObject: map.currentValue) {
field = objects
} else {
field = nil
}
}
// Code targeting the Swift 4.1 compiler and below.
#if !(swift(>=4.1.50) || (swift(>=3.4) && !swift(>=4.0)))
/// Implicitly unwrapped optional mappable object array
class func optionalObjectArray<N: BaseMappable>(_ field: inout Array<N>!, map: Map) {
if let objects: Array<N> = Mapper(context: map.context).mapArray(JSONObject: map.currentValue) {
field = objects
} else {
field = nil
}
}
#endif
/// mappable object array
class func twoDimensionalObjectArray<N: BaseMappable>(_ field: inout Array<Array<N>>, map: Map) {
if let objects = Mapper<N>(context: map.context).mapArrayOfArrays(JSONObject: map.currentValue) {
field = objects
}
}
/// optional mappable 2 dimentional object array
class func optionalTwoDimensionalObjectArray<N: BaseMappable>(_ field: inout Array<Array<N>>?, map: Map) {
field = Mapper(context: map.context).mapArrayOfArrays(JSONObject: map.currentValue)
}
// Code targeting the Swift 4.1 compiler and below.
#if !(swift(>=4.1.50) || (swift(>=3.4) && !swift(>=4.0)))
/// Implicitly unwrapped optional 2 dimentional mappable object array
class func optionalTwoDimensionalObjectArray<N: BaseMappable>(_ field: inout Array<Array<N>>!, map: Map) {
field = Mapper(context: map.context).mapArrayOfArrays(JSONObject: map.currentValue)
}
#endif
/// Dctionary containing Mappable objects
class func objectDictionary<N: BaseMappable>(_ field: inout Dictionary<String, N>, map: Map) {
if map.toObject {
field = Mapper<N>(context: map.context).mapDictionary(JSONObject: map.currentValue, toDictionary: field)
} else {
if let objects = Mapper<N>(context: map.context).mapDictionary(JSONObject: map.currentValue) {
field = objects
}
}
}
/// Optional dictionary containing Mappable objects
class func optionalObjectDictionary<N: BaseMappable>(_ field: inout Dictionary<String, N>?, map: Map) {
if let f = field , map.toObject && map.currentValue != nil {
field = Mapper(context: map.context).mapDictionary(JSONObject: map.currentValue, toDictionary: f)
} else {
field = Mapper(context: map.context).mapDictionary(JSONObject: map.currentValue)
}
}
// Code targeting the Swift 4.1 compiler and below.
#if !(swift(>=4.1.50) || (swift(>=3.4) && !swift(>=4.0)))
/// Implicitly unwrapped Dictionary containing Mappable objects
class func optionalObjectDictionary<N: BaseMappable>(_ field: inout Dictionary<String, N>!, map: Map) {
if let f = field , map.toObject && map.currentValue != nil {
field = Mapper(context: map.context).mapDictionary(JSONObject: map.currentValue, toDictionary: f)
} else {
field = Mapper(context: map.context).mapDictionary(JSONObject: map.currentValue)
}
}
#endif
/// Dictionary containing Array of Mappable objects
class func objectDictionaryOfArrays<N: BaseMappable>(_ field: inout Dictionary<String, [N]>, map: Map) {
if let objects = Mapper<N>(context: map.context).mapDictionaryOfArrays(JSONObject: map.currentValue) {
field = objects
}
}
/// Optional Dictionary containing Array of Mappable objects
class func optionalObjectDictionaryOfArrays<N: BaseMappable>(_ field: inout Dictionary<String, [N]>?, map: Map) {
field = Mapper<N>(context: map.context).mapDictionaryOfArrays(JSONObject: map.currentValue)
}
// Code targeting the Swift 4.1 compiler and below.
#if !(swift(>=4.1.50) || (swift(>=3.4) && !swift(>=4.0)))
/// Implicitly unwrapped Dictionary containing Array of Mappable objects
class func optionalObjectDictionaryOfArrays<N: BaseMappable>(_ field: inout Dictionary<String, [N]>!, map: Map) {
field = Mapper<N>(context: map.context).mapDictionaryOfArrays(JSONObject: map.currentValue)
}
#endif
/// mappable object Set
class func objectSet<N: BaseMappable>(_ field: inout Set<N>, map: Map) {
if let objects = Mapper<N>(context: map.context).mapSet(JSONObject: map.currentValue) {
field = objects
}
}
/// optional mappable object array
class func optionalObjectSet<N: BaseMappable>(_ field: inout Set<N>?, map: Map) {
field = Mapper(context: map.context).mapSet(JSONObject: map.currentValue)
}
// Code targeting the Swift 4.1 compiler and below.
#if !(swift(>=4.1.50) || (swift(>=3.4) && !swift(>=4.0)))
/// Implicitly unwrapped optional mappable object array
class func optionalObjectSet<N: BaseMappable>(_ field: inout Set<N>!, map: Map) {
field = Mapper(context: map.context).mapSet(JSONObject: map.currentValue)
}
#endif
}
+144
View File
@@ -0,0 +1,144 @@
//
// HexColorTransform.swift
// ObjectMapper
//
// Created by Vitaliy Kuzmenko on 10/10/16.
//
// Copyright (c) 2014-2018 Tristan Himmelman
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#if os(iOS) || os(tvOS) || os(watchOS)
import UIKit
#elseif os(macOS)
import Cocoa
#endif
#if os(iOS) || os(tvOS) || os(watchOS) || os(macOS)
open class HexColorTransform: TransformType {
#if os(iOS) || os(tvOS) || os(watchOS)
public typealias Object = UIColor
#else
public typealias Object = NSColor
#endif
public typealias JSON = String
var prefix: Bool = false
var alpha: Bool = false
public init(prefixToJSON: Bool = false, alphaToJSON: Bool = false) {
alpha = alphaToJSON
prefix = prefixToJSON
}
open func transformFromJSON(_ value: Any?) -> Object? {
if let rgba = value as? String {
if rgba.hasPrefix("#") {
let index = rgba.index(rgba.startIndex, offsetBy: 1)
let hex = String(rgba[index...])
return getColor(hex: hex)
} else {
return getColor(hex: rgba)
}
}
return nil
}
open func transformToJSON(_ value: Object?) -> JSON? {
if let value = value {
return hexString(color: value)
}
return nil
}
fileprivate func hexString(color: Object) -> String {
let comps = color.cgColor.components!
let compsCount = color.cgColor.numberOfComponents
let r: Int
let g: Int
var b: Int
let a = Int(comps[compsCount - 1] * 255)
if compsCount == 4 { // RGBA
r = Int(comps[0] * 255)
g = Int(comps[1] * 255)
b = Int(comps[2] * 255)
} else { // Grayscale
r = Int(comps[0] * 255)
g = Int(comps[0] * 255)
b = Int(comps[0] * 255)
}
var hexString: String = ""
if prefix {
hexString = "#"
}
hexString += String(format: "%02X%02X%02X", r, g, b)
if alpha {
hexString += String(format: "%02X", a)
}
return hexString
}
fileprivate func getColor(hex: String) -> Object? {
var red: CGFloat = 0.0
var green: CGFloat = 0.0
var blue: CGFloat = 0.0
var alpha: CGFloat = 1.0
let scanner = Scanner(string: hex)
var hexValue: CUnsignedLongLong = 0
if scanner.scanHexInt64(&hexValue) {
switch (hex.count) {
case 3:
red = CGFloat((hexValue & 0xF00) >> 8) / 15.0
green = CGFloat((hexValue & 0x0F0) >> 4) / 15.0
blue = CGFloat(hexValue & 0x00F) / 15.0
case 4:
red = CGFloat((hexValue & 0xF000) >> 12) / 15.0
green = CGFloat((hexValue & 0x0F00) >> 8) / 15.0
blue = CGFloat((hexValue & 0x00F0) >> 4) / 15.0
alpha = CGFloat(hexValue & 0x000F) / 15.0
case 6:
red = CGFloat((hexValue & 0xFF0000) >> 16) / 255.0
green = CGFloat((hexValue & 0x00FF00) >> 8) / 255.0
blue = CGFloat(hexValue & 0x0000FF) / 255.0
case 8:
red = CGFloat((hexValue & 0xFF000000) >> 24) / 255.0
green = CGFloat((hexValue & 0x00FF0000) >> 16) / 255.0
blue = CGFloat((hexValue & 0x0000FF00) >> 8) / 255.0
alpha = CGFloat(hexValue & 0x000000FF) / 255.0
default:
// Invalid RGB string, number of characters after '#' should be either 3, 4, 6 or 8
return nil
}
} else {
// "Scan hex error
return nil
}
#if os(iOS) || os(tvOS) || os(watchOS)
return UIColor(red: red, green: green, blue: blue, alpha: alpha)
#else
return NSColor(red: red, green: green, blue: blue, alpha: alpha)
#endif
}
}
#endif
@@ -0,0 +1,47 @@
//
// ISO8601DateTransform.swift
// ObjectMapper
//
// Created by Jean-Pierre Mouilleseaux on 21 Nov 2014.
//
// The MIT License (MIT)
//
// Copyright (c) 2014-2018 Tristan Himmelman
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
import Foundation
public extension DateFormatter {
convenience init(withFormat format : String, locale : String) {
self.init()
self.locale = Locale(identifier: locale)
dateFormat = format
}
}
open class ISO8601DateTransform: DateFormatterTransform {
static let reusableISODateFormatter = DateFormatter(withFormat: "yyyy-MM-dd'T'HH:mm:ssZZZZZ", locale: "en_US_POSIX")
public init() {
super.init(dateFormatter: ISO8601DateTransform.reusableISODateFormatter)
}
}
+376
View File
@@ -0,0 +1,376 @@
//
// ImmutableMappble.swift
// ObjectMapper
//
// Created by Suyeol Jeon on 23/09/2016.
//
// The MIT License (MIT)
//
// Copyright (c) 2014-2018 Tristan Himmelman
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
public protocol ImmutableMappable: BaseMappable {
init(map: Map) throws
}
public extension ImmutableMappable {
/// Implement this method to support object -> JSON transform.
func mapping(map: Map) {}
/// Initializes object from a JSON String
init(JSONString: String, context: MapContext? = nil) throws {
self = try Mapper(context: context).map(JSONString: JSONString)
}
/// Initializes object from a JSON Dictionary
init(JSON: [String: Any], context: MapContext? = nil) throws {
self = try Mapper(context: context).map(JSON: JSON)
}
/// Initializes object from a JSONObject
init(JSONObject: Any, context: MapContext? = nil) throws {
self = try Mapper(context: context).map(JSONObject: JSONObject)
}
}
public extension Map {
fileprivate func currentValue(for key: String, nested: Bool? = nil, delimiter: String = ".") -> Any? {
let isNested = nested ?? key.contains(delimiter)
return self[key, nested: isNested, delimiter: delimiter].currentValue
}
// MARK: Basic
/// Returns a value or throws an error.
func value<T>(_ key: String, nested: Bool? = nil, delimiter: String = ".", file: StaticString = #file, function: StaticString = #function, line: UInt = #line) throws -> T {
let currentValue = self.currentValue(for: key, nested: nested, delimiter: delimiter)
guard let value = currentValue as? T else {
throw MapError(key: key, currentValue: currentValue, reason: "Cannot cast to '\(T.self)'", file: file, function: function, line: line)
}
return value
}
/// Returns a transformed value or throws an error.
func value<Transform: TransformType>(_ key: String, nested: Bool? = nil, delimiter: String = ".", using transform: Transform, file: StaticString = #file, function: StaticString = #function, line: UInt = #line) throws -> Transform.Object {
let currentValue = self.currentValue(for: key, nested: nested, delimiter: delimiter)
guard let value = transform.transformFromJSON(currentValue) else {
throw MapError(key: key, currentValue: currentValue, reason: "Cannot transform to '\(Transform.Object.self)' using \(transform)", file: file, function: function, line: line)
}
return value
}
/// Returns a RawRepresentable type or throws an error.
func value<T: RawRepresentable>(_ key: String, nested: Bool? = nil, delimiter: String = ".", file: StaticString = #file, function: StaticString = #function, line: UInt = #line) throws -> T {
return try self.value(key, nested: nested, delimiter: delimiter, using: EnumTransform(), file: file, function: function, line: line)
}
/// Returns a RawRepresentable type or throws an error.
func value<T: RawRepresentable>(_ key: String, nested: Bool? = nil, delimiter: String = ".", file: StaticString = #file, function: StaticString = #function, line: UInt = #line) throws -> T? {
return try self.value(key, nested: nested, delimiter: delimiter, using: EnumTransform(), file: file, function: function, line: line)
}
/// Returns a `[RawRepresentable]` type or throws an error.
func value<T: RawRepresentable>(_ key: String, nested: Bool? = nil, delimiter: String = ".", file: StaticString = #file, function: StaticString = #function, line: UInt = #line) throws -> [T] {
return try self.value(key, nested: nested, delimiter: delimiter, using: EnumTransform(), file: file, function: function, line: line)
}
/// Returns a `[RawRepresentable]` type or throws an error.
func value<T: RawRepresentable>(_ key: String, nested: Bool? = nil, delimiter: String = ".", file: StaticString = #file, function: StaticString = #function, line: UInt = #line) throws -> [T]? {
return try self.value(key, nested: nested, delimiter: delimiter, using: EnumTransform(), file: file, function: function, line: line)
}
// MARK: BaseMappable
/// Returns a `BaseMappable` object or throws an error.
func value<T: BaseMappable>(_ key: String, nested: Bool? = nil, delimiter: String = ".", file: StaticString = #file, function: StaticString = #function, line: UInt = #line) throws -> T {
let currentValue = self.currentValue(for: key, nested: nested, delimiter: delimiter)
guard let JSONObject = currentValue else {
throw MapError(key: key, currentValue: currentValue, reason: "Found unexpected nil value", file: file, function: function, line: line)
}
return try Mapper<T>(context: context).mapOrFail(JSONObject: JSONObject)
}
/// Returns a `BaseMappable` object boxed in `Optional` or throws an error.
func value<T: BaseMappable>(_ key: String, nested: Bool? = nil, delimiter: String = ".", file: StaticString = #file, function: StaticString = #function, line: UInt = #line) throws -> T? {
let currentValue = self.currentValue(for: key, nested: nested, delimiter: delimiter)
guard let JSONObject = currentValue else {
throw MapError(key: key, currentValue: currentValue, reason: "Found unexpected nil value", file: file, function: function, line: line)
}
return try Mapper<T>(context: context).mapOrFail(JSONObject: JSONObject)
}
// MARK: [BaseMappable]
/// Returns a `[BaseMappable]` or throws an error.
func value<T: BaseMappable>(_ key: String, nested: Bool? = nil, delimiter: String = ".", file: StaticString = #file, function: StaticString = #function, line: UInt = #line) throws -> [T] {
let currentValue = self.currentValue(for: key, nested: nested, delimiter: delimiter)
guard let jsonArray = currentValue as? [Any] else {
throw MapError(key: key, currentValue: currentValue, reason: "Cannot cast to '[Any]'", file: file, function: function, line: line)
}
return try jsonArray.map { JSONObject -> T in
return try Mapper<T>(context: context).mapOrFail(JSONObject: JSONObject)
}
}
/// Returns a `[BaseMappable]` boxed in `Optional` or throws an error.
func value<T: BaseMappable>(_ key: String, nested: Bool? = nil, delimiter: String = ".", file: StaticString = #file, function: StaticString = #function, line: UInt = #line) throws -> [T]? {
let currentValue = self.currentValue(for: key, nested: nested, delimiter: delimiter)
guard let jsonArray = currentValue as? [Any] else {
throw MapError(key: key, currentValue: currentValue, reason: "Cannot cast to '[Any]'", file: file, function: function, line: line)
}
return try jsonArray.map { JSONObject -> T in
return try Mapper<T>(context: context).mapOrFail(JSONObject: JSONObject)
}
}
/// Returns a `[BaseMappable]` using transform or throws an error.
func value<Transform: TransformType>(_ key: String, nested: Bool? = nil, delimiter: String = ".", using transform: Transform, file: StaticString = #file, function: StaticString = #function, line: UInt = #line) throws -> [Transform.Object] {
let currentValue = self.currentValue(for: key, nested: nested, delimiter: delimiter)
guard let jsonArray = currentValue as? [Any] else {
throw MapError(key: key, currentValue: currentValue, reason: "Cannot cast to '[Any]'", file: file, function: function, line: line)
}
return try jsonArray.map { json -> Transform.Object in
guard let object = transform.transformFromJSON(json) else {
throw MapError(key: "\(key)", currentValue: json, reason: "Cannot transform to '\(Transform.Object.self)' using \(transform)", file: file, function: function, line: line)
}
return object
}
}
// MARK: [String: BaseMappable]
/// Returns a `[String: BaseMappable]` or throws an error.
func value<T: BaseMappable>(_ key: String, nested: Bool? = nil, delimiter: String = ".", file: StaticString = #file, function: StaticString = #function, line: UInt = #line) throws -> [String: T] {
let currentValue = self.currentValue(for: key, nested: nested, delimiter: delimiter)
guard let jsonDictionary = currentValue as? [String: Any] else {
throw MapError(key: key, currentValue: currentValue, reason: "Cannot cast to '[String: Any]'", file: file, function: function, line: line)
}
return try jsonDictionary.mapValues { json in
return try Mapper<T>(context: context).mapOrFail(JSONObject: json)
}
}
/// Returns a `[String: BaseMappable]` boxed in `Optional` or throws an error.
func value<T: BaseMappable>(_ key: String, nested: Bool? = nil, delimiter: String = ".", file: StaticString = #file, function: StaticString = #function, line: UInt = #line) throws -> [String: T]? {
let currentValue = self.currentValue(for: key, nested: nested, delimiter: delimiter)
guard let jsonDictionary = currentValue as? [String: Any] else {
throw MapError(key: key, currentValue: currentValue, reason: "Cannot cast to '[String: Any]'", file: file, function: function, line: line)
}
var value: [String: T] = [:]
for (key, json) in jsonDictionary {
value[key] = try Mapper<T>(context: context).mapOrFail(JSONObject: json)
}
return value
}
/// Returns a `[String: BaseMappable]` using transform or throws an error.
func value<Transform: TransformType>(_ key: String, nested: Bool? = nil, delimiter: String = ".", using transform: Transform, file: StaticString = #file, function: StaticString = #function, line: UInt = #line) throws -> [String: Transform.Object] {
let currentValue = self.currentValue(for: key, nested: nested, delimiter: delimiter)
guard let jsonDictionary = currentValue as? [String: Any] else {
throw MapError(key: key, currentValue: currentValue, reason: "Cannot cast to '[String: Any]'", file: file, function: function, line: line)
}
return try jsonDictionary.mapValues { json in
guard let object = transform.transformFromJSON(json) else {
throw MapError(key: key, currentValue: json, reason: "Cannot transform to '\(Transform.Object.self)' using \(transform)", file: file, function: function, line: line)
}
return object
}
}
/// Returns a `[String: BaseMappable]` using transform or throws an error.
func value<T: BaseMappable>(_ key: String, nested: Bool? = nil, delimiter: String = ".", file: StaticString = #file, function: StaticString = #function, line: UInt = #line) throws -> [[T]]? {
let currentValue = self.currentValue(for: key, nested: nested, delimiter: delimiter)
guard let json2DArray = currentValue as? [[Any]] else {
throw MapError(key: key, currentValue: currentValue, reason: "Cannot cast to '[[Any]]'", file: file, function: function, line: line)
}
return try json2DArray.map { jsonArray in
try jsonArray.map { jsonObject -> T in
return try Mapper<T>(context: context).mapOrFail(JSONObject: jsonObject)
}
}
}
// MARK: [[BaseMappable]]
/// Returns a `[[BaseMappable]]` or throws an error.
func value<T: BaseMappable>(_ key: String, nested: Bool? = nil, delimiter: String = ".", file: StaticString = #file, function: StaticString = #function, line: UInt = #line) throws -> [[T]] {
let currentValue = self.currentValue(for: key, nested: nested, delimiter: delimiter)
guard let json2DArray = currentValue as? [[Any]] else {
throw MapError(key: key, currentValue: currentValue, reason: "Cannot cast to '[[Any]]'", file: file, function: function, line: line)
}
return try json2DArray.map { jsonArray in
try jsonArray.map { jsonObject -> T in
return try Mapper<T>(context: context).mapOrFail(JSONObject: jsonObject)
}
}
}
/// Returns a `[[BaseMappable]]` using transform or throws an error.
func value<Transform: TransformType>(_ key: String, nested: Bool? = nil, delimiter: String = ".", using transform: Transform, file: StaticString = #file, function: StaticString = #function, line: UInt = #line) throws -> [[Transform.Object]] {
let currentValue = self.currentValue(for: key, nested: nested, delimiter: delimiter)
guard let json2DArray = currentValue as? [[Any]] else {
throw MapError(key: key, currentValue: currentValue, reason: "Cannot cast to '[[Any]]'",
file: file, function: function, line: line)
}
return try json2DArray.map { jsonArray in
try jsonArray.map { json -> Transform.Object in
guard let object = transform.transformFromJSON(json) else {
throw MapError(key: "\(key)", currentValue: json, reason: "Cannot transform to '\(Transform.Object.self)' using \(transform)", file: file, function: function, line: line)
}
return object
}
}
}
}
public extension Mapper where N: ImmutableMappable {
func map(JSON: [String: Any]) throws -> N {
return try self.mapOrFail(JSON: JSON)
}
func map(JSONString: String) throws -> N {
return try mapOrFail(JSONString: JSONString)
}
func map(JSONObject: Any) throws -> N {
return try mapOrFail(JSONObject: JSONObject)
}
// MARK: Array mapping functions
func mapArray(JSONArray: [[String: Any]]) throws -> [N] {
#if swift(>=4.1)
return try JSONArray.compactMap(mapOrFail)
#else
return try JSONArray.flatMap(mapOrFail)
#endif
}
func mapArray(JSONString: String) throws -> [N] {
guard let JSONObject = Mapper.parseJSONString(JSONString: JSONString) else {
throw MapError(key: nil, currentValue: JSONString, reason: "Cannot convert string into Any'")
}
return try mapArray(JSONObject: JSONObject)
}
func mapArray(JSONObject: Any) throws -> [N] {
guard let JSONArray = JSONObject as? [[String: Any]] else {
throw MapError(key: nil, currentValue: JSONObject, reason: "Cannot cast to '[[String: Any]]'")
}
return try mapArray(JSONArray: JSONArray)
}
// MARK: Dictionary mapping functions
func mapDictionary(JSONString: String) throws -> [String: N] {
guard let JSONObject = Mapper.parseJSONString(JSONString: JSONString) else {
throw MapError(key: nil, currentValue: JSONString, reason: "Cannot convert string into Any'")
}
return try mapDictionary(JSONObject: JSONObject)
}
func mapDictionary(JSONObject: Any?) throws -> [String: N] {
guard let JSON = JSONObject as? [String: [String: Any]] else {
throw MapError(key: nil, currentValue: JSONObject, reason: "Cannot cast to '[String: [String: Any]]''")
}
return try mapDictionary(JSON: JSON)
}
func mapDictionary(JSON: [String: [String: Any]]) throws -> [String: N] {
return try JSON.filterMap(mapOrFail)
}
// MARK: Dictinoary of arrays mapping functions
func mapDictionaryOfArrays(JSONObject: Any?) throws -> [String: [N]] {
guard let JSON = JSONObject as? [String: [[String: Any]]] else {
throw MapError(key: nil, currentValue: JSONObject, reason: "Cannot cast to '[String: [String: Any]]''")
}
return try mapDictionaryOfArrays(JSON: JSON)
}
func mapDictionaryOfArrays(JSON: [String: [[String: Any]]]) throws -> [String: [N]] {
return try JSON.filterMap { array -> [N] in
try mapArray(JSONArray: array)
}
}
// MARK: 2 dimentional array mapping functions
func mapArrayOfArrays(JSONObject: Any?) throws -> [[N]] {
guard let JSONArray = JSONObject as? [[[String: Any]]] else {
throw MapError(key: nil, currentValue: JSONObject, reason: "Cannot cast to '[[[String: Any]]]''")
}
return try JSONArray.map(mapArray)
}
}
internal extension Mapper {
func mapOrFail(JSON: [String: Any]) throws -> N {
let map = Map(mappingType: .fromJSON, JSON: JSON, context: context, shouldIncludeNilValues: shouldIncludeNilValues)
// Check if object is ImmutableMappable, if so use ImmutableMappable protocol for mapping
if let klass = N.self as? ImmutableMappable.Type,
var object = try klass.init(map: map) as? N {
object.mapping(map: map)
return object
}
// If not, map the object the standard way
guard let value = self.map(JSON: JSON) else {
throw MapError(key: nil, currentValue: JSON, reason: "Cannot map to '\(N.self)'")
}
return value
}
func mapOrFail(JSONString: String) throws -> N {
guard let JSON = Mapper.parseJSONStringIntoDictionary(JSONString: JSONString) else {
throw MapError(key: nil, currentValue: JSONString, reason: "Cannot parse into '[String: Any]'")
}
return try mapOrFail(JSON: JSON)
}
func mapOrFail(JSONObject: Any) throws -> N {
guard let JSON = JSONObject as? [String: Any] else {
throw MapError(key: nil, currentValue: JSONObject, reason: "Cannot cast to '[String: Any]'")
}
return try mapOrFail(JSON: JSON)
}
}
+171
View File
@@ -0,0 +1,171 @@
//
// IntegerOperators.swift
// ObjectMapper
//
// Created by Suyeol Jeon on 17/02/2017.
//
// The MIT License (MIT)
//
// Copyright (c) 2014-2018 Tristan Himmelman
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
import Foundation
// MARK: - Signed Integer
/// SignedInteger mapping
public func <- <T: SignedInteger>(left: inout T, right: Map) {
switch right.mappingType {
case .fromJSON where right.isKeyPresent:
let value: T = toSignedInteger(right.currentValue) ?? 0
FromJSON.basicType(&left, object: value)
case .toJSON:
left >>> right
default: ()
}
}
/// Optional SignedInteger mapping
public func <- <T: SignedInteger>(left: inout T?, right: Map) {
switch right.mappingType {
case .fromJSON where right.isKeyPresent:
let value: T? = toSignedInteger(right.currentValue)
FromJSON.basicType(&left, object: value)
case .toJSON:
left >>> right
default: ()
}
}
// Code targeting the Swift 4.1 compiler and below.
#if !(swift(>=4.1.50) || (swift(>=3.4) && !swift(>=4.0)))
/// ImplicitlyUnwrappedOptional SignedInteger mapping
public func <- <T: SignedInteger>(left: inout T!, right: Map) {
switch right.mappingType {
case .fromJSON where right.isKeyPresent:
let value: T! = toSignedInteger(right.currentValue)
FromJSON.basicType(&left, object: value)
case .toJSON:
left >>> right
default: ()
}
}
#endif
// MARK: - Unsigned Integer
/// UnsignedInteger mapping
public func <- <T: UnsignedInteger>(left: inout T, right: Map) {
switch right.mappingType {
case .fromJSON where right.isKeyPresent:
let value: T = toUnsignedInteger(right.currentValue) ?? 0
FromJSON.basicType(&left, object: value)
case .toJSON:
left >>> right
default: ()
}
}
/// Optional UnsignedInteger mapping
public func <- <T: UnsignedInteger>(left: inout T?, right: Map) {
switch right.mappingType {
case .fromJSON where right.isKeyPresent:
let value: T? = toUnsignedInteger(right.currentValue)
FromJSON.basicType(&left, object: value)
case .toJSON:
left >>> right
default: ()
}
}
// Code targeting the Swift 4.1 compiler and below.
#if !(swift(>=4.1.50) || (swift(>=3.4) && !swift(>=4.0)))
/// ImplicitlyUnwrappedOptional UnsignedInteger mapping
public func <- <T: UnsignedInteger>(left: inout T!, right: Map) {
switch right.mappingType {
case .fromJSON where right.isKeyPresent:
let value: T! = toUnsignedInteger(right.currentValue)
FromJSON.basicType(&left, object: value)
case .toJSON:
left >>> right
default: ()
}
}
#endif
// MARK: - Casting Utils
/// Convert any value to `SignedInteger`.
private func toSignedInteger<T: SignedInteger>(_ value: Any?) -> T? {
guard
let value = value,
case let number as NSNumber = value
else {
return nil
}
if T.self == Int.self, let x = Int(exactly: number.int64Value) {
return T.init(x)
}
if T.self == Int8.self, let x = Int8(exactly: number.int64Value) {
return T.init(x)
}
if T.self == Int16.self, let x = Int16(exactly: number.int64Value) {
return T.init(x)
}
if T.self == Int32.self, let x = Int32(exactly: number.int64Value) {
return T.init(x)
}
if T.self == Int64.self, let x = Int64(exactly: number.int64Value) {
return T.init(x)
}
return nil
}
/// Convert any value to `UnsignedInteger`.
private func toUnsignedInteger<T: UnsignedInteger>(_ value: Any?) -> T? {
guard
let value = value,
case let number as NSNumber = value
else {
return nil
}
if T.self == UInt.self, let x = UInt(exactly: number.uint64Value) {
return T.init(x)
}
if T.self == UInt8.self, let x = UInt8(exactly: number.uint64Value) {
return T.init(x)
}
if T.self == UInt16.self, let x = UInt16(exactly: number.uint64Value) {
return T.init(x)
}
if T.self == UInt32.self, let x = UInt32(exactly: number.uint64Value) {
return T.init(x)
}
if T.self == UInt64.self, let x = UInt64(exactly: number.uint64Value) {
return T.init(x)
}
return nil
}
+246
View File
@@ -0,0 +1,246 @@
//
// Map.swift
// ObjectMapper
//
// Created by Tristan Himmelman on 2015-10-09.
//
// The MIT License (MIT)
//
// Copyright (c) 2014-2018 Tristan Himmelman
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
import Foundation
/// MapContext is available for developers who wish to pass information around during the mapping process.
public protocol MapContext {
}
/// A class used for holding mapping data
public final class Map {
public let mappingType: MappingType
public internal(set) var JSON: [String: Any] = [:]
public internal(set) var isKeyPresent = false
public internal(set) var currentValue: Any?
public internal(set) var currentKey: String?
var keyIsNested = false
public internal(set) var nestedKeyDelimiter: String = "."
public var context: MapContext?
public var shouldIncludeNilValues = false /// If this is set to true, toJSON output will include null values for any variables that are not set.
public let toObject: Bool // indicates whether the mapping is being applied to an existing object
public init(mappingType: MappingType, JSON: [String: Any], toObject: Bool = false, context: MapContext? = nil, shouldIncludeNilValues: Bool = false) {
self.mappingType = mappingType
self.JSON = JSON
self.toObject = toObject
self.context = context
self.shouldIncludeNilValues = shouldIncludeNilValues
}
/// Sets the current mapper value and key.
/// The Key paramater can be a period separated string (ex. "distance.value") to access sub objects.
public subscript(key: String) -> Map {
// save key and value associated to it
return self.subscript(key: key)
}
public subscript(key: String, delimiter delimiter: String) -> Map {
return self.subscript(key: key, delimiter: delimiter)
}
public subscript(key: String, nested nested: Bool) -> Map {
return self.subscript(key: key, nested: nested)
}
public subscript(key: String, nested nested: Bool, delimiter delimiter: String) -> Map {
return self.subscript(key: key, nested: nested, delimiter: delimiter)
}
public subscript(key: String, ignoreNil ignoreNil: Bool) -> Map {
return self.subscript(key: key, ignoreNil: ignoreNil)
}
public subscript(key: String, delimiter delimiter: String, ignoreNil ignoreNil: Bool) -> Map {
return self.subscript(key: key, delimiter: delimiter, ignoreNil: ignoreNil)
}
public subscript(key: String, nested nested: Bool, ignoreNil ignoreNil: Bool) -> Map {
return self.subscript(key: key, nested: nested, ignoreNil: ignoreNil)
}
public subscript(key: String, nested nested: Bool?, delimiter delimiter: String, ignoreNil ignoreNil: Bool) -> Map {
return self.subscript(key: key, nested: nested, delimiter: delimiter, ignoreNil: ignoreNil)
}
private func `subscript`(key: String, nested: Bool? = nil, delimiter: String = ".", ignoreNil: Bool = false) -> Map {
// save key and value associated to it
currentKey = key
keyIsNested = nested ?? key.contains(delimiter)
nestedKeyDelimiter = delimiter
if mappingType == .fromJSON {
// check if a value exists for the current key
// do this pre-check for performance reasons
if keyIsNested {
// break down the components of the key that are separated by delimiter
(isKeyPresent, currentValue) = valueFor(ArraySlice(key.components(separatedBy: delimiter)), dictionary: JSON)
} else {
let object = JSON[key]
let isNSNull = object is NSNull
isKeyPresent = isNSNull ? true : object != nil
currentValue = isNSNull ? nil : object
}
// update isKeyPresent if ignoreNil is true
if ignoreNil && currentValue == nil {
isKeyPresent = false
}
}
return self
}
public func value<T>() -> T? {
let value = currentValue as? T
// Swift 4.1 breaks Float casting from `NSNumber`. So Added extra checks for `Float` `[Float]` and `[String:Float]`
if value == nil && T.self == Float.self {
if let v = currentValue as? NSNumber {
return v.floatValue as? T
}
} else if value == nil && T.self == [Float].self {
if let v = currentValue as? [Double] {
#if swift(>=4.1)
return v.compactMap{ Float($0) } as? T
#else
return v.flatMap{ Float($0) } as? T
#endif
}
} else if value == nil && T.self == [String:Float].self {
if let v = currentValue as? [String:Double] {
return v.mapValues{ Float($0) } as? T
}
}
return value
}
}
/// Fetch value from JSON dictionary, loop through keyPathComponents until we reach the desired object
private func valueFor(_ keyPathComponents: ArraySlice<String>, dictionary: [String: Any]) -> (Bool, Any?) {
// Implement it as a tail recursive function.
if keyPathComponents.isEmpty {
return (false, nil)
}
if let keyPath = keyPathComponents.first {
let isTail = keyPathComponents.count == 1
let object = dictionary[keyPath]
if object is NSNull {
return (isTail, nil)
} else if keyPathComponents.count > 1, let dict = object as? [String: Any] {
let tail = keyPathComponents.dropFirst()
return valueFor(tail, dictionary: dict)
} else if keyPathComponents.count > 1, let array = object as? [Any] {
let tail = keyPathComponents.dropFirst()
return valueFor(tail, array: array)
} else {
return (isTail && object != nil, object)
}
}
return (false, nil)
}
/// Fetch value from JSON Array, loop through keyPathComponents them until we reach the desired object
private func valueFor(_ keyPathComponents: ArraySlice<String>, array: [Any]) -> (Bool, Any?) {
// Implement it as a tail recursive function.
if keyPathComponents.isEmpty {
return (false, nil)
}
//Try to convert keypath to Int as index
if let keyPath = keyPathComponents.first,
let index = Int(keyPath) , index >= 0 && index < array.count {
let isTail = keyPathComponents.count == 1
let object = array[index]
if object is NSNull {
return (isTail, nil)
} else if keyPathComponents.count > 1, let array = object as? [Any] {
let tail = keyPathComponents.dropFirst()
return valueFor(tail, array: array)
} else if keyPathComponents.count > 1, let dict = object as? [String: Any] {
let tail = keyPathComponents.dropFirst()
return valueFor(tail, dictionary: dict)
} else {
return (isTail, object)
}
}
return (false, nil)
}
// MARK: - Default Value
public extension Map {
/// Returns `default` value if there is nothing to parse.
func value<T>(_ key: String, default: T.Object, using transform: T) throws -> T.Object where T: TransformType {
if let value: T.Object = try? self.value(key, using: transform) {
return value
} else {
return `default`
}
}
/// Returns `default` value if there is nothing to parse.
func value<T>(_ key: String, default: T) throws -> T {
if let value: T = try? self.value(key) {
return value
} else {
return `default`
}
}
/// Returns `default` value if there is nothing to parse.
func value<T: BaseMappable>(_ key: String, default: [T]) -> [T] {
do {
let value: [T] = try self.value(key)
return value
} catch {
return `default`
}
}
/// Returns `default` value if there is nothing to parse.
func value<T>(_ key: String, default: T) throws -> T where T: BaseMappable {
if let value: T = try? self.value(key) as T {
return value
} else {
return `default`
}
}
}
+68
View File
@@ -0,0 +1,68 @@
//
// MapError.swift
// ObjectMapper
//
// Created by Tristan Himmelman on 2016-09-26.
//
// The MIT License (MIT)
//
// Copyright (c) 2014-2018 Tristan Himmelman
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
import Foundation
public struct MapError: Error {
public var key: String?
public var currentValue: Any?
public var reason: String?
public var file: StaticString?
public var function: StaticString?
public var line: UInt?
public init(key: String?, currentValue: Any?, reason: String?, file: StaticString? = nil, function: StaticString? = nil, line: UInt? = nil) {
self.key = key
self.currentValue = currentValue
self.reason = reason
self.file = file
self.function = function
self.line = line
}
}
extension MapError: CustomStringConvertible {
private var location: String? {
guard let file = file, let function = function, let line = line else { return nil }
let fileName = ((String(describing: file).components(separatedBy: "/").last ?? "").components(separatedBy: ".").first ?? "")
return "\(fileName).\(function):\(line)"
}
public var description: String {
let info: [(String, Any?)] = [
("- reason", reason),
("- location", location),
("- key", key),
("- currentValue", currentValue),
]
let infoString = info.map { "\($0.0): \($0.1 ?? "nil")" }.joined(separator: "\n")
return "Got an error while mapping.\n\(infoString)"
}
}
+139
View File
@@ -0,0 +1,139 @@
//
// Mappable.swift
// ObjectMapper
//
// Created by Scott Hoyt on 10/25/15.
//
// The MIT License (MIT)
//
// Copyright (c) 2014-2018 Tristan Himmelman
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
import Foundation
/// BaseMappable should not be implemented directly. Mappable or StaticMappable should be used instead
public protocol BaseMappable {
/// This function is where all variable mappings should occur. It is executed by Mapper during the mapping (serialization and deserialization) process.
mutating func mapping(map: Map)
}
public protocol Mappable: BaseMappable {
/// This function can be used to validate JSON prior to mapping. Return nil to cancel mapping at this point
init?(map: Map)
}
public protocol StaticMappable: BaseMappable {
/// This is function that can be used to:
/// 1) provide an existing cached object to be used for mapping
/// 2) return an object of another class (which conforms to BaseMappable) to be used for mapping. For instance, you may inspect the JSON to infer the type of object that should be used for any given mapping
static func objectForMapping(map: Map) -> BaseMappable?
}
public extension Mappable {
/// Initializes object from a JSON String
init?(JSONString: String, context: MapContext? = nil) {
if let obj: Self = Mapper(context: context).map(JSONString: JSONString) {
self = obj
} else {
return nil
}
}
/// Initializes object from a JSON Dictionary
init?(JSON: [String: Any], context: MapContext? = nil) {
if let obj: Self = Mapper(context: context).map(JSON: JSON) {
self = obj
} else {
return nil
}
}
}
public extension BaseMappable {
/// Returns the JSON Dictionary for the object
func toJSON() -> [String: Any] {
return Mapper().toJSON(self)
}
/// Returns the JSON String for the object
func toJSONString(prettyPrint: Bool = false) -> String? {
return Mapper().toJSONString(self, prettyPrint: prettyPrint)
}
}
public extension Array where Element: BaseMappable {
/// Initialize Array from a JSON String
init?(JSONString: String, context: MapContext? = nil) {
if let obj: [Element] = Mapper(context: context).mapArray(JSONString: JSONString) {
self = obj
} else {
return nil
}
}
/// Initialize Array from a JSON Array
init(JSONArray: [[String: Any]], context: MapContext? = nil) {
let obj: [Element] = Mapper(context: context).mapArray(JSONArray: JSONArray)
self = obj
}
/// Returns the JSON Array
func toJSON() -> [[String: Any]] {
return Mapper().toJSONArray(self)
}
/// Returns the JSON String for the object
func toJSONString(prettyPrint: Bool = false) -> String? {
return Mapper().toJSONString(self, prettyPrint: prettyPrint)
}
}
public extension Set where Element: BaseMappable {
/// Initializes a set from a JSON String
init?(JSONString: String, context: MapContext? = nil) {
if let obj: Set<Element> = Mapper(context: context).mapSet(JSONString: JSONString) {
self = obj
} else {
return nil
}
}
/// Initializes a set from JSON
init?(JSONArray: [[String: Any]], context: MapContext? = nil) {
guard let obj = Mapper(context: context).mapSet(JSONArray: JSONArray) as Set<Element>? else {
return nil
}
self = obj
}
/// Returns the JSON Set
func toJSON() -> [[String: Any]] {
return Mapper().toJSONSet(self)
}
/// Returns the JSON String for the object
func toJSONString(prettyPrint: Bool = false) -> String? {
return Mapper().toJSONString(self, prettyPrint: prettyPrint)
}
}
+493
View File
@@ -0,0 +1,493 @@
//
// Mapper.swift
// ObjectMapper
//
// Created by Tristan Himmelman on 2014-10-09.
//
// The MIT License (MIT)
//
// Copyright (c) 2014-2018 Tristan Himmelman
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
import Foundation
public enum MappingType {
case fromJSON
case toJSON
}
/// The Mapper class provides methods for converting Model objects to JSON and methods for converting JSON to Model objects
public final class Mapper<N: BaseMappable> {
public var context: MapContext?
public var shouldIncludeNilValues = false /// If this is set to true, toJSON output will include null values for any variables that are not set.
public init(context: MapContext? = nil, shouldIncludeNilValues: Bool = false){
self.context = context
self.shouldIncludeNilValues = shouldIncludeNilValues
}
// MARK: Mapping functions that map to an existing object toObject
/// Maps a JSON object to an existing Mappable object if it is a JSON dictionary, or returns the passed object as is
public func map(JSONObject: Any?, toObject object: N) -> N {
if let JSON = JSONObject as? [String: Any] {
return map(JSON: JSON, toObject: object)
}
return object
}
/// Map a JSON string onto an existing object
public func map(JSONString: String, toObject object: N) -> N {
if let JSON = Mapper.parseJSONStringIntoDictionary(JSONString: JSONString) {
return map(JSON: JSON, toObject: object)
}
return object
}
/// Maps a JSON dictionary to an existing object that conforms to Mappable.
/// Usefull for those pesky objects that have crappy designated initializers like NSManagedObject
public func map(JSON: [String: Any], toObject object: N) -> N {
var mutableObject = object
let map = Map(mappingType: .fromJSON, JSON: JSON, toObject: true, context: context, shouldIncludeNilValues: shouldIncludeNilValues)
mutableObject.mapping(map: map)
return mutableObject
}
//MARK: Mapping functions that create an object
/// Map a JSON string to an object that conforms to Mappable
public func map(JSONString: String) -> N? {
if let JSON = Mapper.parseJSONStringIntoDictionary(JSONString: JSONString) {
return map(JSON: JSON)
}
return nil
}
/// Maps a JSON object to a Mappable object if it is a JSON dictionary or NSString, or returns nil.
public func map(JSONObject: Any?) -> N? {
if let JSON = JSONObject as? [String: Any] {
return map(JSON: JSON)
}
return nil
}
/// Maps a JSON dictionary to an object that conforms to Mappable
public func map(JSON: [String: Any]) -> N? {
let map = Map(mappingType: .fromJSON, JSON: JSON, context: context, shouldIncludeNilValues: shouldIncludeNilValues)
if let klass = N.self as? StaticMappable.Type { // Check if object is StaticMappable
if var object = klass.objectForMapping(map: map) as? N {
object.mapping(map: map)
return object
}
} else if let klass = N.self as? Mappable.Type { // Check if object is Mappable
if var object = klass.init(map: map) as? N {
object.mapping(map: map)
return object
}
} else if let klass = N.self as? ImmutableMappable.Type { // Check if object is ImmutableMappable
do {
if var object = try klass.init(map: map) as? N {
object.mapping(map: map)
return object
}
} catch let error {
#if DEBUG
#if !os(Linux)
let exception: NSException
if let mapError = error as? MapError {
exception = NSException(name: .init(rawValue: "MapError"), reason: mapError.description, userInfo: nil)
} else {
exception = NSException(name: .init(rawValue: "ImmutableMappableError"), reason: error.localizedDescription, userInfo: nil)
}
exception.raise()
#endif
#endif
}
} else {
// Ensure BaseMappable is not implemented directly
assert(false, "BaseMappable should not be implemented directly. Please implement Mappable, StaticMappable or ImmutableMappable")
}
return nil
}
// MARK: Mapping functions for Arrays and Dictionaries
/// Maps a JSON array to an object that conforms to Mappable
public func mapArray(JSONString: String) -> [N]? {
let parsedJSON: Any? = Mapper.parseJSONString(JSONString: JSONString)
if let objectArray = mapArray(JSONObject: parsedJSON) {
return objectArray
}
// failed to parse JSON into array form
// try to parse it into a dictionary and then wrap it in an array
if let object = map(JSONObject: parsedJSON) {
return [object]
}
return nil
}
/// Maps a JSON object to an array of Mappable objects if it is an array of JSON dictionary, or returns nil.
public func mapArray(JSONObject: Any?) -> [N]? {
if let JSONArray = JSONObject as? [[String: Any]] {
return mapArray(JSONArray: JSONArray)
}
return nil
}
/// Maps an array of JSON dictionary to an array of Mappable objects
public func mapArray(JSONArray: [[String: Any]]) -> [N] {
// map every element in JSON array to type N
#if swift(>=4.1)
let result = JSONArray.compactMap(map)
#else
let result = JSONArray.flatMap(map)
#endif
return result
}
/// Maps a JSON object to a dictionary of Mappable objects if it is a JSON dictionary of dictionaries, or returns nil.
public func mapDictionary(JSONString: String) -> [String: N]? {
let parsedJSON: Any? = Mapper.parseJSONString(JSONString: JSONString)
return mapDictionary(JSONObject: parsedJSON)
}
/// Maps a JSON object to a dictionary of Mappable objects if it is a JSON dictionary of dictionaries, or returns nil.
public func mapDictionary(JSONObject: Any?) -> [String: N]? {
if let JSON = JSONObject as? [String: [String: Any]] {
return mapDictionary(JSON: JSON)
}
return nil
}
/// Maps a JSON dictionary of dictionaries to a dictionary of Mappable objects
public func mapDictionary(JSON: [String: [String: Any]]) -> [String: N]? {
// map every value in dictionary to type N
let result = JSON.filterMap(map)
if !result.isEmpty {
return result
}
return nil
}
/// Maps a JSON object to a dictionary of Mappable objects if it is a JSON dictionary of dictionaries, or returns nil.
public func mapDictionary(JSONObject: Any?, toDictionary dictionary: [String: N]) -> [String: N] {
if let JSON = JSONObject as? [String : [String : Any]] {
return mapDictionary(JSON: JSON, toDictionary: dictionary)
}
return dictionary
}
/// Maps a JSON dictionary of dictionaries to an existing dictionary of Mappable objects
public func mapDictionary(JSON: [String: [String: Any]], toDictionary dictionary: [String: N]) -> [String: N] {
var mutableDictionary = dictionary
for (key, value) in JSON {
if let object = dictionary[key] {
_ = map(JSON: value, toObject: object)
} else {
mutableDictionary[key] = map(JSON: value)
}
}
return mutableDictionary
}
/// Maps a JSON object to a dictionary of arrays of Mappable objects
public func mapDictionaryOfArrays(JSONObject: Any?) -> [String: [N]]? {
if let JSON = JSONObject as? [String: [[String: Any]]] {
return mapDictionaryOfArrays(JSON: JSON)
}
return nil
}
///Maps a JSON dictionary of arrays to a dictionary of arrays of Mappable objects
public func mapDictionaryOfArrays(JSON: [String: [[String: Any]]]) -> [String: [N]]? {
// map every value in dictionary to type N
let result = JSON.filterMap {
mapArray(JSONArray: $0)
}
if !result.isEmpty {
return result
}
return nil
}
/// Maps an 2 dimentional array of JSON dictionaries to a 2 dimentional array of Mappable objects
public func mapArrayOfArrays(JSONObject: Any?) -> [[N]]? {
if let JSONArray = JSONObject as? [[[String: Any]]] {
let objectArray = JSONArray.map { innerJSONArray in
return mapArray(JSONArray: innerJSONArray)
}
if !objectArray.isEmpty {
return objectArray
}
}
return nil
}
// MARK: Utility functions for converting strings to JSON objects
/// Convert a JSON String into a Dictionary<String, Any> using NSJSONSerialization
public static func parseJSONStringIntoDictionary(JSONString: String) -> [String: Any]? {
let parsedJSON: Any? = Mapper.parseJSONString(JSONString: JSONString)
return parsedJSON as? [String: Any]
}
/// Convert a JSON String into an Object using NSJSONSerialization
public static func parseJSONString(JSONString: String) -> Any? {
let data = JSONString.data(using: String.Encoding.utf8, allowLossyConversion: true)
if let data = data {
let parsedJSON: Any?
do {
parsedJSON = try JSONSerialization.jsonObject(with: data, options: JSONSerialization.ReadingOptions.allowFragments)
} catch let error {
print(error)
parsedJSON = nil
}
return parsedJSON
}
return nil
}
}
extension Mapper {
// MARK: Functions that create model from JSON file
/// JSON file to Mappable object
/// - parameter JSONfile: Filename
/// - Returns: Mappable object
public func map(JSONfile: String) -> N? {
if let path = Bundle.main.path(forResource: JSONfile, ofType: nil) {
do {
let JSONString = try String(contentsOfFile: path)
do {
return self.map(JSONString: JSONString)
}
} catch {
return nil
}
}
return nil
}
/// JSON file to Mappable object array
/// - parameter JSONfile: Filename
/// - Returns: Mappable object array
public func mapArray(JSONfile: String) -> [N]? {
if let path = Bundle.main.path(forResource: JSONfile, ofType: nil) {
do {
let JSONString = try String(contentsOfFile: path)
do {
return self.mapArray(JSONString: JSONString)
}
} catch {
return nil
}
}
return nil
}
}
extension Mapper {
// MARK: Functions that create JSON from objects
///Maps an object that conforms to Mappable to a JSON dictionary <String, Any>
public func toJSON(_ object: N) -> [String: Any] {
var mutableObject = object
let map = Map(mappingType: .toJSON, JSON: [:], context: context, shouldIncludeNilValues: shouldIncludeNilValues)
mutableObject.mapping(map: map)
return map.JSON
}
///Maps an array of Objects to an array of JSON dictionaries [[String: Any]]
public func toJSONArray(_ array: [N]) -> [[String: Any]] {
return array.map {
// convert every element in array to JSON dictionary equivalent
self.toJSON($0)
}
}
///Maps a dictionary of Objects that conform to Mappable to a JSON dictionary of dictionaries.
public func toJSONDictionary(_ dictionary: [String: N]) -> [String: [String: Any]] {
return dictionary.map { (arg: (key: String, value: N)) in
// convert every value in dictionary to its JSON dictionary equivalent
return (arg.key, self.toJSON(arg.value))
}
}
///Maps a dictionary of Objects that conform to Mappable to a JSON dictionary of dictionaries.
public func toJSONDictionaryOfArrays(_ dictionary: [String: [N]]) -> [String: [[String: Any]]] {
return dictionary.map { (arg: (key: String, value: [N])) in
// convert every value (array) in dictionary to its JSON dictionary equivalent
return (arg.key, self.toJSONArray(arg.value))
}
}
/// Maps an Object to a JSON string with option of pretty formatting
public func toJSONString(_ object: N, prettyPrint: Bool = false) -> String? {
let JSONDict = toJSON(object)
return Mapper.toJSONString(JSONDict as Any, prettyPrint: prettyPrint)
}
/// Maps an array of Objects to a JSON string with option of pretty formatting
public func toJSONString(_ array: [N], prettyPrint: Bool = false) -> String? {
let JSONDict = toJSONArray(array)
return Mapper.toJSONString(JSONDict as Any, prettyPrint: prettyPrint)
}
/// Converts an Object to a JSON string with option of pretty formatting
public static func toJSONString(_ JSONObject: Any, prettyPrint: Bool) -> String? {
let options: JSONSerialization.WritingOptions = prettyPrint ? .prettyPrinted : []
if let JSON = Mapper.toJSONData(JSONObject, options: options) {
return String(data: JSON, encoding: String.Encoding.utf8)
}
return nil
}
/// Converts an Object to JSON data with options
public static func toJSONData(_ JSONObject: Any, options: JSONSerialization.WritingOptions) -> Data? {
if JSONSerialization.isValidJSONObject(JSONObject) {
let JSONData: Data?
do {
JSONData = try JSONSerialization.data(withJSONObject: JSONObject, options: options)
} catch let error {
print(error)
JSONData = nil
}
return JSONData
}
return nil
}
}
extension Mapper where N: Hashable {
/// Maps a JSON array to an object that conforms to Mappable
public func mapSet(JSONString: String) -> Set<N>? {
let parsedJSON: Any? = Mapper.parseJSONString(JSONString: JSONString)
if let objectArray = mapArray(JSONObject: parsedJSON) {
return Set(objectArray)
}
// failed to parse JSON into array form
// try to parse it into a dictionary and then wrap it in an array
if let object = map(JSONObject: parsedJSON) {
return Set([object])
}
return nil
}
/// Maps a JSON object to an Set of Mappable objects if it is an array of JSON dictionary, or returns nil.
public func mapSet(JSONObject: Any?) -> Set<N>? {
if let JSONArray = JSONObject as? [[String: Any]] {
return mapSet(JSONArray: JSONArray)
}
return nil
}
/// Maps an Set of JSON dictionary to an array of Mappable objects
public func mapSet(JSONArray: [[String: Any]]) -> Set<N> {
// map every element in JSON array to type N
#if swift(>=4.1)
return Set(JSONArray.compactMap(map))
#else
return Set(JSONArray.flatMap(map))
#endif
}
///Maps a Set of Objects to a Set of JSON dictionaries [[String : Any]]
public func toJSONSet(_ set: Set<N>) -> [[String: Any]] {
return set.map {
// convert every element in set to JSON dictionary equivalent
self.toJSON($0)
}
}
/// Maps a set of Objects to a JSON string with option of pretty formatting
public func toJSONString(_ set: Set<N>, prettyPrint: Bool = false) -> String? {
let JSONDict = toJSONSet(set)
return Mapper.toJSONString(JSONDict as Any, prettyPrint: prettyPrint)
}
}
extension Dictionary {
internal func map<K, V>(_ f: (Element) throws -> (K, V)) rethrows -> [K: V] {
var mapped = [K: V]()
for element in self {
let newElement = try f(element)
mapped[newElement.0] = newElement.1
}
return mapped
}
internal func map<K, V>(_ f: (Element) throws -> (K, [V])) rethrows -> [K: [V]] {
var mapped = [K: [V]]()
for element in self {
let newElement = try f(element)
mapped[newElement.0] = newElement.1
}
return mapped
}
internal func filterMap<U>(_ f: (Value) throws -> U?) rethrows -> [Key: U] {
var mapped = [Key: U]()
for (key, value) in self {
if let newValue = try f(value) {
mapped[key] = newValue
}
}
return mapped
}
}
@@ -0,0 +1,52 @@
//
// TransformOf.swift
// ObjectMapper
//
// Created by Tristan Himmelman on 8/22/16.
//
// The MIT License (MIT)
//
// Copyright (c) 2014-2018 Tristan Himmelman
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
import Foundation
open class NSDecimalNumberTransform: TransformType {
public typealias Object = NSDecimalNumber
public typealias JSON = String
public init() {}
open func transformFromJSON(_ value: Any?) -> NSDecimalNumber? {
if let string = value as? String {
return NSDecimalNumber(string: string)
} else if let number = value as? NSNumber {
return NSDecimalNumber(decimal: number.decimalValue)
} else if let double = value as? Double {
return NSDecimalNumber(floatLiteral: double)
}
return nil
}
open func transformToJSON(_ value: NSDecimalNumber?) -> String? {
guard let value = value else { return nil }
return value.description
}
}
+398
View File
@@ -0,0 +1,398 @@
//
// Operators.swift
// ObjectMapper
//
// Created by Tristan Himmelman on 2014-10-09.
//
// The MIT License (MIT)
//
// Copyright (c) 2014-2018 Tristan Himmelman
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
/**
* This file defines a new operator which is used to create a mapping between an object and a JSON key value.
* There is an overloaded operator definition for each type of object that is supported in ObjectMapper.
* This provides a way to add custom logic to handle specific types of objects
*/
/// Operator used for defining mappings to and from JSON
infix operator <-
/// Operator used to define mappings to JSON
infix operator >>>
// MARK:- Objects with Basic types
/// Object of Basic type
public func <- <T>(left: inout T, right: Map) {
switch right.mappingType {
case .fromJSON where right.isKeyPresent:
FromJSON.basicType(&left, object: right.value())
case .toJSON:
left >>> right
default: ()
}
}
public func >>> <T>(left: T, right: Map) {
if right.mappingType == .toJSON {
ToJSON.basicType(left, map: right)
}
}
/// Optional object of basic type
public func <- <T>(left: inout T?, right: Map) {
switch right.mappingType {
case .fromJSON where right.isKeyPresent:
FromJSON.optionalBasicType(&left, object: right.value())
case .toJSON:
left >>> right
default: ()
}
}
public func >>> <T>(left: T?, right: Map) {
if right.mappingType == .toJSON {
ToJSON.optionalBasicType(left, map: right)
}
}
// Code targeting the Swift 4.1 compiler and below.
#if !(swift(>=4.1.50) || (swift(>=3.4) && !swift(>=4.0)))
/// Implicitly unwrapped optional object of basic type
public func <- <T>(left: inout T!, right: Map) {
switch right.mappingType {
case .fromJSON where right.isKeyPresent:
FromJSON.optionalBasicType(&left, object: right.value())
case .toJSON:
left >>> right
default: ()
}
}
#endif
// MARK:- Mappable Objects - <T: BaseMappable>
/// Object conforming to Mappable
public func <- <T: BaseMappable>(left: inout T, right: Map) {
switch right.mappingType {
case .fromJSON:
FromJSON.object(&left, map: right)
case .toJSON:
left >>> right
}
}
public func >>> <T: BaseMappable>(left: T, right: Map) {
if right.mappingType == .toJSON {
ToJSON.object(left, map: right)
}
}
/// Optional Mappable objects
public func <- <T: BaseMappable>(left: inout T?, right: Map) {
switch right.mappingType {
case .fromJSON where right.isKeyPresent:
FromJSON.optionalObject(&left, map: right)
case .toJSON:
left >>> right
default: ()
}
}
public func >>> <T: BaseMappable>(left: T?, right: Map) {
if right.mappingType == .toJSON {
ToJSON.optionalObject(left, map: right)
}
}
// Code targeting the Swift 4.1 compiler and below.
#if !(swift(>=4.1.50) || (swift(>=3.4) && !swift(>=4.0)))
/// Implicitly unwrapped optional Mappable objects
public func <- <T: BaseMappable>(left: inout T!, right: Map) {
switch right.mappingType {
case .fromJSON where right.isKeyPresent:
FromJSON.optionalObject(&left, map: right)
case .toJSON:
left >>> right
default: ()
}
}
#endif
// MARK:- Dictionary of Mappable objects - Dictionary<String, T: BaseMappable>
/// Dictionary of Mappable objects <String, T: Mappable>
public func <- <T: BaseMappable>(left: inout Dictionary<String, T>, right: Map) {
switch right.mappingType {
case .fromJSON where right.isKeyPresent:
FromJSON.objectDictionary(&left, map: right)
case .toJSON:
left >>> right
default: ()
}
}
public func >>> <T: BaseMappable>(left: Dictionary<String, T>, right: Map) {
if right.mappingType == .toJSON {
ToJSON.objectDictionary(left, map: right)
}
}
/// Optional Dictionary of Mappable object <String, T: Mappable>
public func <- <T: BaseMappable>(left: inout Dictionary<String, T>?, right: Map) {
switch right.mappingType {
case .fromJSON where right.isKeyPresent:
FromJSON.optionalObjectDictionary(&left, map: right)
case .toJSON:
left >>> right
default: ()
}
}
public func >>> <T: BaseMappable>(left: Dictionary<String, T>?, right: Map) {
if right.mappingType == .toJSON {
ToJSON.optionalObjectDictionary(left, map: right)
}
}
// Code targeting the Swift 4.1 compiler and below.
#if !(swift(>=4.1.50) || (swift(>=3.4) && !swift(>=4.0)))
/// Implicitly unwrapped Optional Dictionary of Mappable object <String, T: Mappable>
public func <- <T: BaseMappable>(left: inout Dictionary<String, T>!, right: Map) {
switch right.mappingType {
case .fromJSON where right.isKeyPresent:
FromJSON.optionalObjectDictionary(&left, map: right)
case .toJSON:
left >>> right
default: ()
}
}
#endif
/// Dictionary of Mappable objects <String, T: Mappable>
public func <- <T: BaseMappable>(left: inout Dictionary<String, [T]>, right: Map) {
switch right.mappingType {
case .fromJSON where right.isKeyPresent:
FromJSON.objectDictionaryOfArrays(&left, map: right)
case .toJSON:
left >>> right
default: ()
}
}
public func >>> <T: BaseMappable>(left: Dictionary<String, [T]>, right: Map) {
if right.mappingType == .toJSON {
ToJSON.objectDictionaryOfArrays(left, map: right)
}
}
/// Optional Dictionary of Mappable object <String, T: Mappable>
public func <- <T: BaseMappable>(left: inout Dictionary<String, [T]>?, right: Map) {
switch right.mappingType {
case .fromJSON where right.isKeyPresent:
FromJSON.optionalObjectDictionaryOfArrays(&left, map: right)
case .toJSON:
left >>> right
default: ()
}
}
public func >>> <T: BaseMappable>(left: Dictionary<String, [T]>?, right: Map) {
if right.mappingType == .toJSON {
ToJSON.optionalObjectDictionaryOfArrays(left, map: right)
}
}
// Code targeting the Swift 4.1 compiler and below.
#if !(swift(>=4.1.50) || (swift(>=3.4) && !swift(>=4.0)))
/// Implicitly unwrapped Optional Dictionary of Mappable object <String, T: Mappable>
public func <- <T: BaseMappable>(left: inout Dictionary<String, [T]>!, right: Map) {
switch right.mappingType {
case .fromJSON where right.isKeyPresent:
FromJSON.optionalObjectDictionaryOfArrays(&left, map: right)
case .toJSON:
left >>> right
default: ()
}
}
#endif
// MARK:- Array of Mappable objects - Array<T: BaseMappable>
/// Array of Mappable objects
public func <- <T: BaseMappable>(left: inout Array<T>, right: Map) {
switch right.mappingType {
case .fromJSON where right.isKeyPresent:
FromJSON.objectArray(&left, map: right)
case .toJSON:
left >>> right
default: ()
}
}
public func >>> <T: BaseMappable>(left: Array<T>, right: Map) {
if right.mappingType == .toJSON {
ToJSON.objectArray(left, map: right)
}
}
/// Optional array of Mappable objects
public func <- <T: BaseMappable>(left: inout Array<T>?, right: Map) {
switch right.mappingType {
case .fromJSON where right.isKeyPresent:
FromJSON.optionalObjectArray(&left, map: right)
case .toJSON:
left >>> right
default: ()
}
}
public func >>> <T: BaseMappable>(left: Array<T>?, right: Map) {
if right.mappingType == .toJSON {
ToJSON.optionalObjectArray(left, map: right)
}
}
// Code targeting the Swift 4.1 compiler and below.
#if !(swift(>=4.1.50) || (swift(>=3.4) && !swift(>=4.0)))
/// Implicitly unwrapped Optional array of Mappable objects
public func <- <T: BaseMappable>(left: inout Array<T>!, right: Map) {
switch right.mappingType {
case .fromJSON where right.isKeyPresent:
FromJSON.optionalObjectArray(&left, map: right)
case .toJSON:
left >>> right
default: ()
}
}
#endif
// MARK:- Array of Array of Mappable objects - Array<Array<T: BaseMappable>>
/// Array of Array Mappable objects
public func <- <T: BaseMappable>(left: inout Array<Array<T>>, right: Map) {
switch right.mappingType {
case .fromJSON where right.isKeyPresent:
FromJSON.twoDimensionalObjectArray(&left, map: right)
case .toJSON:
left >>> right
default: ()
}
}
public func >>> <T: BaseMappable>(left: Array<Array<T>>, right: Map) {
if right.mappingType == .toJSON {
ToJSON.twoDimensionalObjectArray(left, map: right)
}
}
/// Optional array of Mappable objects
public func <- <T: BaseMappable>(left:inout Array<Array<T>>?, right: Map) {
switch right.mappingType {
case .fromJSON where right.isKeyPresent:
FromJSON.optionalTwoDimensionalObjectArray(&left, map: right)
case .toJSON:
left >>> right
default: ()
}
}
public func >>> <T: BaseMappable>(left: Array<Array<T>>?, right: Map) {
if right.mappingType == .toJSON {
ToJSON.optionalTwoDimensionalObjectArray(left, map: right)
}
}
// Code targeting the Swift 4.1 compiler and below.
#if !(swift(>=4.1.50) || (swift(>=3.4) && !swift(>=4.0)))
/// Implicitly unwrapped Optional array of Mappable objects
public func <- <T: BaseMappable>(left: inout Array<Array<T>>!, right: Map) {
switch right.mappingType {
case .fromJSON where right.isKeyPresent:
FromJSON.optionalTwoDimensionalObjectArray(&left, map: right)
case .toJSON:
left >>> right
default: ()
}
}
#endif
// MARK:- Set of Mappable objects - Set<T: BaseMappable>
/// Set of Mappable objects
public func <- <T: BaseMappable>(left: inout Set<T>, right: Map) {
switch right.mappingType {
case .fromJSON where right.isKeyPresent:
FromJSON.objectSet(&left, map: right)
case .toJSON:
left >>> right
default: ()
}
}
public func >>> <T: BaseMappable>(left: Set<T>, right: Map) {
if right.mappingType == .toJSON {
ToJSON.objectSet(left, map: right)
}
}
/// Optional Set of Mappable objects
public func <- <T: BaseMappable>(left: inout Set<T>?, right: Map) {
switch right.mappingType {
case .fromJSON where right.isKeyPresent:
FromJSON.optionalObjectSet(&left, map: right)
case .toJSON:
left >>> right
default: ()
}
}
public func >>> <T: BaseMappable>(left: Set<T>?, right: Map) {
if right.mappingType == .toJSON {
ToJSON.optionalObjectSet(left, map: right)
}
}
// Code targeting the Swift 4.1 compiler and below.
#if !(swift(>=4.1.50) || (swift(>=3.4) && !swift(>=4.0)))
/// Implicitly unwrapped Optional Set of Mappable objects
public func <- <T: BaseMappable>(left: inout Set<T>!, right: Map) {
switch right.mappingType {
case .fromJSON where right.isKeyPresent:
FromJSON.optionalObjectSet(&left, map: right)
case .toJSON:
left >>> right
default: ()
}
}
#endif
+177
View File
@@ -0,0 +1,177 @@
//
// ToJSON.swift
// ObjectMapper
//
// Created by Tristan Himmelman on 2014-10-13.
//
// The MIT License (MIT)
//
// Copyright (c) 2014-2018 Tristan Himmelman
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
import Foundation
private func setValue(_ value: Any, map: Map) {
setValue(value, key: map.currentKey!, checkForNestedKeys: map.keyIsNested, delimiter: map.nestedKeyDelimiter, dictionary: &map.JSON)
}
private func setValue(_ value: Any, key: String, checkForNestedKeys: Bool, delimiter: String, dictionary: inout [String : Any]) {
if checkForNestedKeys {
let keyComponents = ArraySlice(key.components(separatedBy: delimiter).filter { !$0.isEmpty }.map { $0 })
setValue(value, forKeyPathComponents: keyComponents, dictionary: &dictionary)
} else {
dictionary[key] = value
}
}
private func setValue(_ value: Any, forKeyPathComponents components: ArraySlice<String>, dictionary: inout [String : Any]) {
guard let head = components.first else {
return
}
let headAsString = String(head)
if components.count == 1 {
dictionary[headAsString] = value
} else {
var child = dictionary[headAsString] as? [String : Any] ?? [:]
let tail = components.dropFirst()
setValue(value, forKeyPathComponents: tail, dictionary: &child)
dictionary[headAsString] = child
}
}
internal final class ToJSON {
class func basicType<N>(_ field: N, map: Map) {
if let x = field as Any? , false
|| x is NSNumber // Basic types
|| x is Bool
|| x is Int
|| x is Double
|| x is Float
|| x is String
|| x is NSNull
|| x is Array<NSNumber> // Arrays
|| x is Array<Bool>
|| x is Array<Int>
|| x is Array<Double>
|| x is Array<Float>
|| x is Array<String>
|| x is Array<Any>
|| x is Array<Dictionary<String, Any>>
|| x is Dictionary<String, NSNumber> // Dictionaries
|| x is Dictionary<String, Bool>
|| x is Dictionary<String, Int>
|| x is Dictionary<String, Double>
|| x is Dictionary<String, Float>
|| x is Dictionary<String, String>
|| x is Dictionary<String, Any>
{
setValue(x, map: map)
}
}
class func optionalBasicType<N>(_ field: N?, map: Map) {
if let field = field {
basicType(field, map: map)
} else if map.shouldIncludeNilValues {
basicType(NSNull(), map: map) //If BasicType is nil, emit NSNull into the JSON output
}
}
class func object<N: BaseMappable>(_ field: N, map: Map) {
if let result = Mapper(context: map.context, shouldIncludeNilValues: map.shouldIncludeNilValues).toJSON(field) as Any? {
setValue(result, map: map)
}
}
class func optionalObject<N: BaseMappable>(_ field: N?, map: Map) {
if let field = field {
object(field, map: map)
} else if map.shouldIncludeNilValues {
basicType(NSNull(), map: map) //If field is nil, emit NSNull into the JSON output
}
}
class func objectArray<N: BaseMappable>(_ field: Array<N>, map: Map) {
let JSONObjects = Mapper(context: map.context, shouldIncludeNilValues: map.shouldIncludeNilValues).toJSONArray(field)
setValue(JSONObjects, map: map)
}
class func optionalObjectArray<N: BaseMappable>(_ field: Array<N>?, map: Map) {
if let field = field {
objectArray(field, map: map)
}
}
class func twoDimensionalObjectArray<N: BaseMappable>(_ field: Array<Array<N>>, map: Map) {
var array = [[[String: Any]]]()
for innerArray in field {
let JSONObjects = Mapper(context: map.context, shouldIncludeNilValues: map.shouldIncludeNilValues).toJSONArray(innerArray)
array.append(JSONObjects)
}
setValue(array, map: map)
}
class func optionalTwoDimensionalObjectArray<N: BaseMappable>(_ field: Array<Array<N>>?, map: Map) {
if let field = field {
twoDimensionalObjectArray(field, map: map)
}
}
class func objectSet<N: BaseMappable>(_ field: Set<N>, map: Map) {
let JSONObjects = Mapper(context: map.context, shouldIncludeNilValues: map.shouldIncludeNilValues).toJSONSet(field)
setValue(JSONObjects, map: map)
}
class func optionalObjectSet<N: BaseMappable>(_ field: Set<N>?, map: Map) {
if let field = field {
objectSet(field, map: map)
}
}
class func objectDictionary<N: BaseMappable>(_ field: Dictionary<String, N>, map: Map) {
let JSONObjects = Mapper(context: map.context, shouldIncludeNilValues: map.shouldIncludeNilValues).toJSONDictionary(field)
setValue(JSONObjects, map: map)
}
class func optionalObjectDictionary<N: BaseMappable>(_ field: Dictionary<String, N>?, map: Map) {
if let field = field {
objectDictionary(field, map: map)
}
}
class func objectDictionaryOfArrays<N: BaseMappable>(_ field: Dictionary<String, [N]>, map: Map) {
let JSONObjects = Mapper(context: map.context, shouldIncludeNilValues: map.shouldIncludeNilValues).toJSONDictionaryOfArrays(field)
setValue(JSONObjects, map: map)
}
class func optionalObjectDictionaryOfArrays<N: BaseMappable>(_ field: Dictionary<String, [N]>?, map: Map) {
if let field = field {
objectDictionaryOfArrays(field, map: map)
}
}
}
+48
View File
@@ -0,0 +1,48 @@
//
// TransformOf.swift
// ObjectMapper
//
// Created by Syo Ikeda on 1/23/15.
//
// The MIT License (MIT)
//
// Copyright (c) 2014-2018 Tristan Himmelman
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
open class TransformOf<ObjectType, JSONType>: TransformType {
public typealias Object = ObjectType
public typealias JSON = JSONType
private let fromJSON: (JSONType?) -> ObjectType?
private let toJSON: (ObjectType?) -> JSONType?
public init(fromJSON: @escaping(JSONType?) -> ObjectType?, toJSON: @escaping(ObjectType?) -> JSONType?) {
self.fromJSON = fromJSON
self.toJSON = toJSON
}
open func transformFromJSON(_ value: Any?) -> ObjectType? {
return fromJSON(value as? JSONType)
}
open func transformToJSON(_ value: ObjectType?) -> JSONType? {
return toJSON(value)
}
}
+709
View File
@@ -0,0 +1,709 @@
//
// TransformOperators.swift
// ObjectMapper
//
// Created by Tristan Himmelman on 2016-09-26.
//
// The MIT License (MIT)
//
// Copyright (c) 2014-2018 Tristan Himmelman
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
import Foundation
// MARK:- Transforms
/// Object of Basic type with Transform
public func <- <Transform: TransformType>(left: inout Transform.Object, right: (Map, Transform)) {
let (map, transform) = right
switch map.mappingType {
case .fromJSON where map.isKeyPresent:
let value = transform.transformFromJSON(map.currentValue)
FromJSON.basicType(&left, object: value)
case .toJSON:
left >>> right
default: ()
}
}
public func >>> <Transform: TransformType>(left: Transform.Object, right: (Map, Transform)) {
let (map, transform) = right
if map.mappingType == .toJSON {
let value: Transform.JSON? = transform.transformToJSON(left)
ToJSON.optionalBasicType(value, map: map)
}
}
/// Optional object of basic type with Transform
public func <- <Transform: TransformType>(left: inout Transform.Object?, right: (Map, Transform)) {
let (map, transform) = right
switch map.mappingType {
case .fromJSON where map.isKeyPresent:
let value = transform.transformFromJSON(map.currentValue)
FromJSON.optionalBasicType(&left, object: value)
case .toJSON:
left >>> right
default: ()
}
}
public func >>> <Transform: TransformType>(left: Transform.Object?, right: (Map, Transform)) {
let (map, transform) = right
if map.mappingType == .toJSON {
let value: Transform.JSON? = transform.transformToJSON(left)
ToJSON.optionalBasicType(value, map: map)
}
}
// Code targeting the Swift 4.1 compiler and below.
#if !(swift(>=4.1.50) || (swift(>=3.4) && !swift(>=4.0)))
/// Implicitly unwrapped optional object of basic type with Transform
public func <- <Transform: TransformType>(left: inout Transform.Object!, right: (Map, Transform)) {
let (map, transform) = right
switch map.mappingType {
case .fromJSON where map.isKeyPresent:
let value = transform.transformFromJSON(map.currentValue)
FromJSON.optionalBasicType(&left, object: value)
case .toJSON:
left >>> right
default: ()
}
}
#endif
/// Array of Basic type with Transform
public func <- <Transform: TransformType>(left: inout [Transform.Object], right: (Map, Transform)) {
let (map, transform) = right
switch map.mappingType {
case .fromJSON where map.isKeyPresent:
let values = fromJSONArrayWithTransform(map.currentValue, transform: transform)
FromJSON.basicType(&left, object: values)
case .toJSON:
left >>> right
default: ()
}
}
public func >>> <Transform: TransformType>(left: [Transform.Object], right: (Map, Transform)) {
let (map, transform) = right
if map.mappingType == .toJSON{
let values = toJSONArrayWithTransform(left, transform: transform)
ToJSON.optionalBasicType(values, map: map)
}
}
/// Optional array of Basic type with Transform
public func <- <Transform: TransformType>(left: inout [Transform.Object]?, right: (Map, Transform)) {
let (map, transform) = right
switch map.mappingType {
case .fromJSON where map.isKeyPresent:
let values = fromJSONArrayWithTransform(map.currentValue, transform: transform)
FromJSON.optionalBasicType(&left, object: values)
case .toJSON:
left >>> right
default: ()
}
}
public func >>> <Transform: TransformType>(left: [Transform.Object]?, right: (Map, Transform)) {
let (map, transform) = right
if map.mappingType == .toJSON {
let values = toJSONArrayWithTransform(left, transform: transform)
ToJSON.optionalBasicType(values, map: map)
}
}
// Code targeting the Swift 4.1 compiler and below.
#if !(swift(>=4.1.50) || (swift(>=3.4) && !swift(>=4.0)))
/// Implicitly unwrapped optional array of Basic type with Transform
public func <- <Transform: TransformType>(left: inout [Transform.Object]!, right: (Map, Transform)) {
let (map, transform) = right
switch map.mappingType {
case .fromJSON where map.isKeyPresent:
let values = fromJSONArrayWithTransform(map.currentValue, transform: transform)
FromJSON.optionalBasicType(&left, object: values)
case .toJSON:
left >>> right
default: ()
}
}
#endif
/// Dictionary of Basic type with Transform
public func <- <Transform: TransformType>(left: inout [String: Transform.Object], right: (Map, Transform)) {
let (map, transform) = right
switch map.mappingType {
case .fromJSON where map.isKeyPresent:
let values = fromJSONDictionaryWithTransform(map.currentValue, transform: transform)
FromJSON.basicType(&left, object: values)
case .toJSON:
left >>> right
default: ()
}
}
public func >>> <Transform: TransformType>(left: [String: Transform.Object], right: (Map, Transform)) {
let (map, transform) = right
if map.mappingType == . toJSON {
let values = toJSONDictionaryWithTransform(left, transform: transform)
ToJSON.optionalBasicType(values, map: map)
}
}
/// Optional dictionary of Basic type with Transform
public func <- <Transform: TransformType>(left: inout [String: Transform.Object]?, right: (Map, Transform)) {
let (map, transform) = right
switch map.mappingType {
case .fromJSON where map.isKeyPresent:
let values = fromJSONDictionaryWithTransform(map.currentValue, transform: transform)
FromJSON.optionalBasicType(&left, object: values)
case .toJSON:
left >>> right
default: ()
}
}
public func >>> <Transform: TransformType>(left: [String: Transform.Object]?, right: (Map, Transform)) {
let (map, transform) = right
if map.mappingType == .toJSON {
let values = toJSONDictionaryWithTransform(left, transform: transform)
ToJSON.optionalBasicType(values, map: map)
}
}
// Code targeting the Swift 4.1 compiler and below.
#if !(swift(>=4.1.50) || (swift(>=3.4) && !swift(>=4.0)))
/// Implicitly unwrapped optional dictionary of Basic type with Transform
public func <- <Transform: TransformType>(left: inout [String: Transform.Object]!, right: (Map, Transform)) {
let (map, transform) = right
switch map.mappingType {
case .fromJSON where map.isKeyPresent:
let values = fromJSONDictionaryWithTransform(map.currentValue, transform: transform)
FromJSON.optionalBasicType(&left, object: values)
case .toJSON:
left >>> right
default: ()
}
}
#endif
// MARK:- Transforms of Mappable Objects - <T: BaseMappable>
/// Object conforming to Mappable that have transforms
public func <- <Transform: TransformType>(left: inout Transform.Object, right: (Map, Transform)) where Transform.Object: BaseMappable {
let (map, transform) = right
switch map.mappingType {
case .fromJSON where map.isKeyPresent:
let value: Transform.Object? = transform.transformFromJSON(map.currentValue)
FromJSON.basicType(&left, object: value)
case .toJSON:
left >>> right
default: ()
}
}
public func >>> <Transform: TransformType>(left: Transform.Object, right: (Map, Transform)) where Transform.Object: BaseMappable {
let (map, transform) = right
if map.mappingType == .toJSON {
let value: Transform.JSON? = transform.transformToJSON(left)
ToJSON.optionalBasicType(value, map: map)
}
}
/// Optional Mappable objects that have transforms
public func <- <Transform: TransformType>(left: inout Transform.Object?, right: (Map, Transform)) where Transform.Object: BaseMappable {
let (map, transform) = right
switch map.mappingType {
case .fromJSON where map.isKeyPresent:
let value: Transform.Object? = transform.transformFromJSON(map.currentValue)
FromJSON.optionalBasicType(&left, object: value)
case .toJSON:
left >>> right
default: ()
}
}
public func >>> <Transform: TransformType>(left: Transform.Object?, right: (Map, Transform)) where Transform.Object: BaseMappable {
let (map, transform) = right
if map.mappingType == .toJSON{
let value: Transform.JSON? = transform.transformToJSON(left)
ToJSON.optionalBasicType(value, map: map)
}
}
// Code targeting the Swift 4.1 compiler and below.
#if !(swift(>=4.1.50) || (swift(>=3.4) && !swift(>=4.0)))
/// Implicitly unwrapped optional Mappable objects that have transforms
public func <- <Transform: TransformType>(left: inout Transform.Object!, right: (Map, Transform)) where Transform.Object: BaseMappable {
let (map, transform) = right
switch map.mappingType {
case .fromJSON where map.isKeyPresent:
let value: Transform.Object? = transform.transformFromJSON(map.currentValue)
FromJSON.optionalBasicType(&left, object: value)
case .toJSON:
left >>> right
default: ()
}
}
#endif
// MARK:- Dictionary of Mappable objects with a transform - Dictionary<String, T: BaseMappable>
/// Dictionary of Mappable objects <String, T: Mappable> with a transform
public func <- <Transform: TransformType>(left: inout Dictionary<String, Transform.Object>, right: (Map, Transform)) where Transform.Object: BaseMappable {
let (map, transform) = right
if map.mappingType == .fromJSON && map.isKeyPresent,
let object = map.currentValue as? [String: Any] {
let value = fromJSONDictionaryWithTransform(object as Any?, transform: transform) ?? left
FromJSON.basicType(&left, object: value)
} else if map.mappingType == .toJSON {
left >>> right
}
}
public func >>> <Transform: TransformType>(left: Dictionary<String, Transform.Object>, right: (Map, Transform)) where Transform.Object: BaseMappable {
let (map, transform) = right
if map.mappingType == .toJSON {
let value = toJSONDictionaryWithTransform(left, transform: transform)
ToJSON.basicType(value, map: map)
}
}
/// Optional Dictionary of Mappable object <String, T: Mappable> with a transform
public func <- <Transform: TransformType>(left: inout Dictionary<String, Transform.Object>?, right: (Map, Transform)) where Transform.Object: BaseMappable {
let (map, transform) = right
if map.mappingType == .fromJSON && map.isKeyPresent, let object = map.currentValue as? [String : Any]{
let value = fromJSONDictionaryWithTransform(object as Any?, transform: transform) ?? left
FromJSON.optionalBasicType(&left, object: value)
} else if map.mappingType == .toJSON {
left >>> right
}
}
public func >>> <Transform: TransformType>(left: Dictionary<String, Transform.Object>?, right: (Map, Transform)) where Transform.Object: BaseMappable {
let (map, transform) = right
if map.mappingType == .toJSON {
let value = toJSONDictionaryWithTransform(left, transform: transform)
ToJSON.optionalBasicType(value, map: map)
}
}
// Code targeting the Swift 4.1 compiler and below.
#if !(swift(>=4.1.50) || (swift(>=3.4) && !swift(>=4.0)))
/// Implicitly unwrapped Optional Dictionary of Mappable object <String, T: Mappable> with a transform
public func <- <Transform: TransformType>(left: inout Dictionary<String, Transform.Object>!, right: (Map, Transform)) where Transform.Object: BaseMappable {
let (map, transform) = right
if map.mappingType == .fromJSON && map.isKeyPresent, let dictionary = map.currentValue as? [String : Any]{
let transformedDictionary = fromJSONDictionaryWithTransform(dictionary as Any?, transform: transform) ?? left
FromJSON.optionalBasicType(&left, object: transformedDictionary)
} else if map.mappingType == .toJSON {
left >>> right
}
}
#endif
/// Dictionary of Mappable objects <String, T: Mappable> with a transform
public func <- <Transform: TransformType>(left: inout Dictionary<String, [Transform.Object]>, right: (Map, Transform)) where Transform.Object: BaseMappable {
let (map, transform) = right
if let dictionary = map.currentValue as? [String : [Any]], map.mappingType == .fromJSON && map.isKeyPresent {
let transformedDictionary = dictionary.map { (arg: (key: String, values: [Any])) -> (String, [Transform.Object]) in
let (key, values) = arg
if let jsonArray = fromJSONArrayWithTransform(values, transform: transform) {
return (key, jsonArray)
}
if let leftValue = left[key] {
return (key, leftValue)
}
return (key, [])
}
FromJSON.basicType(&left, object: transformedDictionary)
} else if map.mappingType == .toJSON {
left >>> right
}
}
public func >>> <Transform: TransformType>(left: Dictionary<String, [Transform.Object]>, right: (Map, Transform)) where Transform.Object: BaseMappable {
let (map, transform) = right
if map.mappingType == .toJSON {
let transformedDictionary = left.map { (arg: (key: String, value: [Transform.Object])) in
return (arg.key, toJSONArrayWithTransform(arg.value, transform: transform) ?? [])
}
ToJSON.basicType(transformedDictionary, map: map)
}
}
/// Optional Dictionary of Mappable object <String, T: Mappable> with a transform
public func <- <Transform: TransformType>(left: inout Dictionary<String, [Transform.Object]>?, right: (Map, Transform)) where Transform.Object: BaseMappable {
let (map, transform) = right
if let dictionary = map.currentValue as? [String : [Any]], map.mappingType == .fromJSON && map.isKeyPresent {
let transformedDictionary = dictionary.map { (arg: (key: String, values: [Any])) -> (String, [Transform.Object]) in
let (key, values) = arg
if let jsonArray = fromJSONArrayWithTransform(values, transform: transform) {
return (key, jsonArray)
}
if let leftValue = left?[key] {
return (key, leftValue)
}
return (key, [])
}
FromJSON.optionalBasicType(&left, object: transformedDictionary)
} else if map.mappingType == .toJSON {
left >>> right
}
}
public func >>> <Transform: TransformType>(left: Dictionary<String, [Transform.Object]>?, right: (Map, Transform)) where Transform.Object: BaseMappable {
let (map, transform) = right
if map.mappingType == .toJSON {
let transformedDictionary = left?.map { (arg: (key: String, values: [Transform.Object])) in
return (arg.key, toJSONArrayWithTransform(arg.values, transform: transform) ?? [])
}
ToJSON.optionalBasicType(transformedDictionary, map: map)
}
}
// Code targeting the Swift 4.1 compiler and below.
#if !(swift(>=4.1.50) || (swift(>=3.4) && !swift(>=4.0)))
/// Implicitly unwrapped Optional Dictionary of Mappable object <String, T: Mappable> with a transform
public func <- <Transform: TransformType>(left: inout Dictionary<String, [Transform.Object]>!, right: (Map, Transform)) where Transform.Object: BaseMappable {
let (map, transform) = right
if let dictionary = map.currentValue as? [String : [Any]], map.mappingType == .fromJSON && map.isKeyPresent {
let transformedDictionary = dictionary.map { (arg: (key: String, values: [Any])) -> (String, [Transform.Object]) in
let (key, values) = arg
if let jsonArray = fromJSONArrayWithTransform(values, transform: transform) {
return (key, jsonArray)
}
if let leftValue = left?[key] {
return (key, leftValue)
}
return (key, [])
}
FromJSON.optionalBasicType(&left, object: transformedDictionary)
} else if map.mappingType == .toJSON {
left >>> right
}
}
#endif
// MARK:- Array of Mappable objects with transforms - Array<T: BaseMappable>
/// Array of Mappable objects
public func <- <Transform: TransformType>(left: inout Array<Transform.Object>, right: (Map, Transform)) where Transform.Object: BaseMappable {
let (map, transform) = right
switch map.mappingType {
case .fromJSON where map.isKeyPresent:
if let transformedValues = fromJSONArrayWithTransform(map.currentValue, transform: transform) {
FromJSON.basicType(&left, object: transformedValues)
}
case .toJSON:
left >>> right
default: ()
}
}
public func >>> <Transform: TransformType>(left: Array<Transform.Object>, right: (Map, Transform)) where Transform.Object: BaseMappable {
let (map, transform) = right
if map.mappingType == .toJSON {
let transformedValues = toJSONArrayWithTransform(left, transform: transform)
ToJSON.optionalBasicType(transformedValues, map: map)
}
}
/// Optional array of Mappable objects
public func <- <Transform: TransformType>(left: inout Array<Transform.Object>?, right: (Map, Transform)) where Transform.Object: BaseMappable {
let (map, transform) = right
switch map.mappingType {
case .fromJSON where map.isKeyPresent:
let transformedValues = fromJSONArrayWithTransform(map.currentValue, transform: transform)
FromJSON.optionalBasicType(&left, object: transformedValues)
case .toJSON:
left >>> right
default: ()
}
}
public func >>> <Transform: TransformType>(left: Array<Transform.Object>?, right: (Map, Transform)) where Transform.Object: BaseMappable {
let (map, transform) = right
if map.mappingType == .toJSON {
let transformedValues = toJSONArrayWithTransform(left, transform: transform)
ToJSON.optionalBasicType(transformedValues, map: map)
}
}
// Code targeting the Swift 4.1 compiler and below.
#if !(swift(>=4.1.50) || (swift(>=3.4) && !swift(>=4.0)))
/// Implicitly unwrapped Optional array of Mappable objects
public func <- <Transform: TransformType>(left: inout Array<Transform.Object>!, right: (Map, Transform)) where Transform.Object: BaseMappable {
let (map, transform) = right
switch map.mappingType {
case .fromJSON where map.isKeyPresent:
let transformedValues = fromJSONArrayWithTransform(map.currentValue, transform: transform)
FromJSON.optionalBasicType(&left, object: transformedValues)
case .toJSON:
left >>> right
default: ()
}
}
#endif
// MARK:- Array of Array of objects - Array<Array<T>>> with transforms
/// Array of Array of objects with transform
public func <- <Transform: TransformType>(left: inout [[Transform.Object]], right: (Map, Transform)) {
let (map, transform) = right
switch map.mappingType {
case .toJSON:
left >>> right
case .fromJSON where map.isKeyPresent:
guard let original2DArray = map.currentValue as? [[Any]] else { break }
#if swift(>=4.1)
let transformed2DArray = original2DArray.compactMap { values in
fromJSONArrayWithTransform(values as Any?, transform: transform)
}
#else
let transformed2DArray = original2DArray.flatMap { values in
fromJSONArrayWithTransform(values as Any?, transform: transform)
}
#endif
FromJSON.basicType(&left, object: transformed2DArray)
default:
break
}
}
public func >>> <Transform: TransformType>(left: [[Transform.Object]], right: (Map, Transform)) {
let (map, transform) = right
if map.mappingType == .toJSON{
#if swift(>=4.1)
let transformed2DArray = left.compactMap { values in
toJSONArrayWithTransform(values, transform: transform)
}
#else
let transformed2DArray = left.flatMap { values in
toJSONArrayWithTransform(values, transform: transform)
}
#endif
ToJSON.basicType(transformed2DArray, map: map)
}
}
/// Optional array of array of objects with transform
public func <- <Transform: TransformType>(left: inout [[Transform.Object]]?, right: (Map, Transform)) {
let (map, transform) = right
switch map.mappingType {
case .toJSON:
left >>> right
case .fromJSON where map.isKeyPresent:
guard let original2DArray = map.currentValue as? [[Any]] else { break }
#if swift(>=4.1)
let transformed2DArray = original2DArray.compactMap { values in
fromJSONArrayWithTransform(values as Any?, transform: transform)
}
#else
let transformed2DArray = original2DArray.flatMap { values in
fromJSONArrayWithTransform(values as Any?, transform: transform)
}
#endif
FromJSON.optionalBasicType(&left, object: transformed2DArray)
default:
break
}
}
public func >>> <Transform: TransformType>(left: [[Transform.Object]]?, right: (Map, Transform)) {
let (map, transform) = right
if map.mappingType == .toJSON {
#if swift(>=4.1)
let transformed2DArray = left?.compactMap { values in
toJSONArrayWithTransform(values, transform: transform)
}
#else
let transformed2DArray = left?.flatMap { values in
toJSONArrayWithTransform(values, transform: transform)
}
#endif
ToJSON.optionalBasicType(transformed2DArray, map: map)
}
}
// Code targeting the Swift 4.1 compiler and below.
#if !(swift(>=4.1.50) || (swift(>=3.4) && !swift(>=4.0)))
/// Implicitly unwrapped Optional array of array of objects with transform
public func <- <Transform: TransformType>(left: inout [[Transform.Object]]!, right: (Map, Transform)) {
let (map, transform) = right
switch map.mappingType {
case .toJSON:
left >>> right
case .fromJSON where map.isKeyPresent:
guard let original2DArray = map.currentValue as? [[Any]] else { break }
#if swift(>=4.1)
let transformed2DArray = original2DArray.compactMap { values in
fromJSONArrayWithTransform(values as Any?, transform: transform)
}
#else
let transformed2DArray = original2DArray.flatMap { values in
fromJSONArrayWithTransform(values as Any?, transform: transform)
}
#endif
FromJSON.optionalBasicType(&left, object: transformed2DArray)
default:
break
}
}
#endif
// MARK:- Set of Mappable objects with a transform - Set<T: BaseMappable>
/// Set of Mappable objects with transform
public func <- <Transform: TransformType>(left: inout Set<Transform.Object>, right: (Map, Transform)) where Transform.Object: BaseMappable {
let (map, transform) = right
switch map.mappingType {
case .fromJSON where map.isKeyPresent:
if let transformedValues = fromJSONArrayWithTransform(map.currentValue, transform: transform) {
FromJSON.basicType(&left, object: Set(transformedValues))
}
case .toJSON:
left >>> right
default: ()
}
}
public func >>> <Transform: TransformType>(left: Set<Transform.Object>, right: (Map, Transform)) where Transform.Object: BaseMappable {
let (map, transform) = right
if map.mappingType == .toJSON {
let transformedValues = toJSONArrayWithTransform(Array(left), transform: transform)
ToJSON.optionalBasicType(transformedValues, map: map)
}
}
/// Optional Set of Mappable objects with transform
public func <- <Transform: TransformType>(left: inout Set<Transform.Object>?, right: (Map, Transform)) where Transform.Object: BaseMappable {
let (map, transform) = right
switch map.mappingType {
case .fromJSON where map.isKeyPresent:
if let transformedValues = fromJSONArrayWithTransform(map.currentValue, transform: transform) {
FromJSON.basicType(&left, object: Set(transformedValues))
}
case .toJSON:
left >>> right
default: ()
}
}
public func >>> <Transform: TransformType>(left: Set<Transform.Object>?, right: (Map, Transform)) where Transform.Object: BaseMappable {
let (map, transform) = right
if map.mappingType == .toJSON {
if let values = left {
let transformedValues = toJSONArrayWithTransform(Array(values), transform: transform)
ToJSON.optionalBasicType(transformedValues, map: map)
}
}
}
// Code targeting the Swift 4.1 compiler and below.
#if !(swift(>=4.1.50) || (swift(>=3.4) && !swift(>=4.0)))
/// Implicitly unwrapped Optional set of Mappable objects with transform
public func <- <Transform: TransformType>(left: inout Set<Transform.Object>!, right: (Map, Transform)) where Transform.Object: BaseMappable {
let (map, transform) = right
switch map.mappingType {
case .fromJSON where map.isKeyPresent:
if let transformedValues = fromJSONArrayWithTransform(map.currentValue, transform: transform) {
FromJSON.basicType(&left, object: Set(transformedValues))
}
case .toJSON:
left >>> right
default: ()
}
}
#endif
private func fromJSONArrayWithTransform<Transform: TransformType>(_ input: Any?, transform: Transform) -> [Transform.Object]? {
if let values = input as? [Any] {
#if swift(>=4.1)
return values.compactMap { value in
return transform.transformFromJSON(value)
}
#else
return values.flatMap { value in
return transform.transformFromJSON(value)
}
#endif
} else {
return nil
}
}
private func fromJSONDictionaryWithTransform<Transform: TransformType>(_ input: Any?, transform: Transform) -> [String: Transform.Object]? {
if let values = input as? [String: Any] {
return values.filterMap { value in
return transform.transformFromJSON(value)
}
} else {
return nil
}
}
private func toJSONArrayWithTransform<Transform: TransformType>(_ input: [Transform.Object]?, transform: Transform) -> [Transform.JSON]? {
#if swift(>=4.1)
return input?.compactMap { value in
return transform.transformToJSON(value)
}
#else
return input?.flatMap { value in
return transform.transformToJSON(value)
}
#endif
}
private func toJSONDictionaryWithTransform<Transform: TransformType>(_ input: [String: Transform.Object]?, transform: Transform) -> [String: Transform.JSON]? {
return input?.filterMap { value in
return transform.transformToJSON(value)
}
}
+35
View File
@@ -0,0 +1,35 @@
//
// TransformType.swift
// ObjectMapper
//
// Created by Syo Ikeda on 2/4/15.
//
// The MIT License (MIT)
//
// Copyright (c) 2014-2018 Tristan Himmelman
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
public protocol TransformType {
associatedtype Object
associatedtype JSON
func transformFromJSON(_ value: Any?) -> Object?
func transformToJSON(_ value: Object?) -> JSON?
}
+67
View File
@@ -0,0 +1,67 @@
//
// URLTransform.swift
// ObjectMapper
//
// Created by Tristan Himmelman on 2014-10-27.
//
// The MIT License (MIT)
//
// Copyright (c) 2014-2018 Tristan Himmelman
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
import Foundation
open class URLTransform: TransformType {
public typealias Object = URL
public typealias JSON = String
private let shouldEncodeURLString: Bool
private let allowedCharacterSet: CharacterSet
/**
Initializes the URLTransform with an option to encode URL strings before converting them to an NSURL
- parameter shouldEncodeUrlString: when true (the default) the string is encoded before passing
to `NSURL(string:)`
- returns: an initialized transformer
*/
public init(shouldEncodeURLString: Bool = false, allowedCharacterSet: CharacterSet = .urlQueryAllowed) {
self.shouldEncodeURLString = shouldEncodeURLString
self.allowedCharacterSet = allowedCharacterSet
}
open func transformFromJSON(_ value: Any?) -> URL? {
guard let URLString = value as? String else { return nil }
if !shouldEncodeURLString {
return URL(string: URLString)
}
guard let escapedURLString = URLString.addingPercentEncoding(withAllowedCharacters: allowedCharacterSet) else {
return nil
}
return URL(string: escapedURLString)
}
open func transformToJSON(_ value: URL?) -> String? {
if let URL = value {
return URL.absoluteString
}
return nil
}
}