ObjectMapper源码笔记(二)

上述主要了解的ObjectMapper的基本使用和核心的文件,此篇文章主要记述了ObjectMapper的各个文件的详解。

Mappable

这个文件中主要定义了可映射的协议组。
可映射协议组

  • BaseMappable:抽象协议,不能直接使用。
// 定义了mapping方法
mutating func mapping(map: Map)
  • Mappable :继承BaseMappable协议。
//在映射之前使用这个方法去验证Json数据,返回nil的时候就取消映射
init?(map: Map)
  • StaticMappable :继承BaseMappable协议。
//1. 提供用于映射的现有对象 2. 返回另一个符合BaseMappable协议的类对象用于映射。
static func objectForMapping(map: Map) -> BaseMappable?
  • BaseMappable扩展:在BaseMappable扩展中默认实现如下协议。主要使用Mapper映射的方法实现。
// 从JSON字符串中初始化对象
public init?(JSONString: String, context: MapContext? = nil) 
// 从JSON字典中初始化对象
public init?(JSON: [String: Any], context: MapContext? = nil)
// 将对象转换到JSON字典
public func toJSON() -> [String: Any]
// 将对象转换到JSON字符串
public func toJSONString(prettyPrint: Bool = false) -> String?
  • Array扩展:Array中元素符合BaseMappable协议,重写上述扩展协议方法。主要使用Mapper映射器的方法实现

  • Set扩展:Set中元素符合BaseMappable协议,重写上述扩展协议方法。主要使用Mappe映射器的方法实现


Map

这个文件中主要定义了Map类持有映射的数据。
Map类中的属性和方法

在Map类中定义了一组下标方法:主要作用得到一个持有key和value的Map实例。

// 这个方法的参数 key:键值,nested:是否嵌套(一般根据分隔符判断),delimiter:分割符,ignoreNil:是否忽略nil值
public subscript(key: String, nested nested: Bool, delimiter delimiter: String, ignoreNil ignoreNil: Bool) -> Map {
        // save key and value associated to it
        // 规定currentKey 当前key ,keyIsNested 键值是否嵌套, nestedKeyDelimiter 嵌套key值的分隔符
        currentKey = key
        keyIsNested = nested
        nestedKeyDelimiter = delimiter

        if mappingType == .fromJSON {  // 从JSON中
            // check if a value exists for the current key
            // do this pre-check for performance reasons
            if nested == false { // 没有嵌套
                let object = JSON[key]
                let isNSNull = object is NSNull
                isKeyPresent = isNSNull ? true : object != nil // 当是null值,isKeyPresent是true;否则,当object不是nil的时候显示
                currentValue = isNSNull ? nil : object // 当是null值,当前值是nil,否者是当是object
            } else { // 嵌套中
                // break down the components of the key that are separated by . 根据分隔符产生数组,从中获取元组(是否显示key,当前值)
                (isKeyPresent, currentValue) = valueFor(ArraySlice(key.components(separatedBy: delimiter)), dictionary: JSON)
            }

            // update isKeyPresent if ignoreNil is true
            if ignoreNil && currentValue == nil { // 如果忽略nil值,同时currentValue为nil的时候,不显示key值
                isKeyPresent = false
            }
        }
        return self  // toJSON类型直接返回self
    }

两个valueFor私有方法:分别针对字典类型和数组类型,解嵌套。两者之间会有递归和相互调用。

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 { // keyPathComponents = [bestFriend,username]
        let object = dictionary[keyPath]
        if object is NSNull { // 如果object是NSNull类型,返回(true, nil)
            return (true, nil)
        } else if keyPathComponents.count > 1, let dict = object as? [String: Any] { // 如果object是字典型,同时keyPathComponents大于1
            let tail = keyPathComponents.dropFirst() // 放弃第一个key值
            return valueFor(tail, dictionary: dict) // 再次调用自己
        } else if keyPathComponents.count > 1, let array = object as? [Any] { // 如果object是数组型,同时keyPathComponents大于1
            let tail = keyPathComponents.dropFirst() // 放弃第一个key值
            return valueFor(tail, array: array) // 调用array的方法
        } else {
            return (object != nil, object) // 返回此类型
        }
    }

    return (false, nil) // 默认返回这个数据
}

Mapper

这个文件定义了泛型类型Mapper<N: BaseMappable> ,这个类是作为映射器使用,提供了数据和模型之间的转换过程方法。
Mapper的方法和属性

单一值类型

map方法的参数分别为JSONObject,JSONString和JSON三种类型。
1. 首先对于JSONString的map方法,是有Mapper类的解析方法parseJSONStringIntoDictionary 将字符串解析至字典。
2. 对于JSONObject的map方法,使用as? 关键字将对象转换至字典。
3. 最后调用的方法都是JSON字典的map方法。

指定的对象map方法:

public func map(JSON: [String: Any], toObject object: N) -> N {
        var mutableObject = object
        // 创建map对象,调用mapping方法。返对象
        let map = Map(mappingType: .fromJSON, JSON: JSON, toObject: true, context: context, shouldIncludeNilValues: shouldIncludeNilValues)
        mutableObject.mapping(map: map)
        return mutableObject
    }

非指定对象map方法:

扫描二维码关注公众号,回复: 2265105 查看本文章
public func map(JSON: [String: Any]) -> N? {
        // 创建一个Map类,从JSON中获取
        let map = Map(mappingType: .fromJSON, JSON: JSON, context: context, shouldIncludeNilValues: shouldIncludeNilValues)
        // 获取N的类型,并匹配相应的类型
        if let klass = N.self as? StaticMappable.Type { // Check if object is StaticMappable
            // 如果是StaticMappable静态映射实例,从map中解除一个BaseMapple实例,转换成N类型的值
            if var object = klass.objectForMapping(map: map) as? N {
                object.mapping(map: map) // 实现BaseMappablede的mapping方法
                return object // 返回object值
            }
        } else if let klass = N.self as? Mappable.Type { // Check if object is Mappable
            // 如果是Mappable实例,实现Mappable的初始化协议并转换成N的类型
            if var object = klass.init(map: map) as? N {
                object.mapping(map: map) // 实现BaseMappablede的mapping方法
                return object // 返回object值
            }
        } else if let klass = N.self as? ImmutableMappable.Type { // Check if object is ImmutableMappable
            // 如果是不可变的Mappable
            do {
                return try klass.init(map: map) as? N // 转换成功返回object值
            } catch let error {
                #if DEBUG
                let exception: NSException
                // 转换成MapError类型
                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()
                #else
                NSLog("\(error)")
                #endif
            }
        } else {
            // Ensure BaseMappable is not implemented directly 确保BaseMappale不能直接别实现
            assert(false, "BaseMappable should not be implemented directly. Please implement Mappable, StaticMappable or ImmutableMappable")
        }

        return nil // 默认返回nil
    }
集合值类型

同单一值类型相同,我们的参数分别为JSONObject,JSONString和JSON三种类型。而我们最终调取JSON字典类型map方法进行操作。

mapArray : 一维数组的对象集合,flatmap方法中调用的map方法是func map(JSON: [String: Any]) -> N? 方法。即将数组中的每一个字典进行映射。

    public func mapArray(JSONArray: [[String: Any]]) -> [N] {
        // map every element in JSON array to type N 
        let result = JSONArray.flatMap(map)
        return result
    }

mapDictionary : 一维字典的对象集合,filterMap方法中调用的map方法是func map(JSON: [String: Any]) -> N? 方法。即将字典中的每一个字典进行映射。

public func mapDictionary(JSON: [String: [String: Any]]) -> [String: N]? {
        // map every value in dictionary to type N
        // filterMap:自定义筛选方法,Dictionary扩展方法,当map成功添加到字典中,否则不添加
        let result = JSON.filterMap(map)
        if result.isEmpty == false { // 筛选结果不为空
            return result
        }
        return nil
    }

mapDictionary:toDictionary:指定字典的映射类型

 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] { // 从key值解出一个对象
                _ = map(JSON: value, toObject: object) // 通过JSON和目标对象进行映射
            } else {
                mutableDictionary[key] = map(JSON: value) // 通过字典映射
            }
        }
        return mutableDictionary
    }

mapDictionaryOfArrays: 字典嵌套数组的集合类型,对于字典中的每一个数组进行mapArray 的方法调用

    public func mapDictionaryOfArrays(JSON: [String: [[String: Any]]]) -> [String: [N]]? {
        // map every value in dictionary to type N
        let result = JSON.filterMap { 
            mapArray(JSONArray: $0) // 从JSON数组中获取[[String: Any]]中获取[N]
        }

        if result.isEmpty == false {
            return result
        }
        return nil
    }

mapArrayOfArrays:双重数组嵌套类型

public func mapArrayOfArrays(JSONObject: Any?) -> [[N]]? {
        if let JSONArray = JSONObject as? [[[String: Any]]] { // 转换类型 [[[:]]] 三重嵌套
            var objectArray = [[N]]()
            for innerJSONArray in JSONArray { // innerJSONArray 是 [[:]]
                //调用mapArray返回,[N]
                let array = mapArray(JSONArray: innerJSONArray)
                objectArray.append(array) // 添加进对象数组中 [[N]]
            }
            if objectArray.isEmpty == false { // 返回结果不为空
            return objectArray
            }
        }
        return nil
    }
toJSON方法

toJSON主要分为转换成字典类型,字符串类型和Data数据类型。

字典核心方法:

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
    }

Data数据类型核心方法:

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) // JSON解析成数据类型
            } catch let error {
                print(error)
                JSONData = nil // 设置是nil值
            }
            return JSONData
        }
        return nil
    }

字符串类型核心方法:将对象转换成Data数据,通过编码转化字符串类型

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) // 从数据中UTF-8编码方式转换成字符串
        }
        return nil
    }

猜你喜欢

转载自blog.csdn.net/m0_38055718/article/details/80626790