ObjectMapperDeep 0.20.3

ObjectMapperDeep 0.20.3

测试测试
Lang语言 SwiftSwift
许可证 MIT
发布上次发布2016年2月
SPM支持 SPM

李建棠维护。



ObjectMapper

ObjectMapper 是一个用 Swift 编写的框架,它使您能够轻松地将 Model 对象(类和结构体)与 JSON 之间相互转换。

特性

  • 将 JSON 映射到对象
  • 将对象映射到 JSON
  • 嵌套对象(独立,在数组或字典中)
  • 映射过程中自定义转换
  • 结构体支持

基础知识

为了支持映射,类或结构体只需要实现 Mappable 协议。

public protocol Mappable {
    init?(_ map: Map)
    mutating func mapping(map: Map)
}

ObjectMapper 使用 <- 操作符来定义每个成员变量如何映射到和从 JSON。

class User: Mappable {
    var username: String?
    var age: Int?
    var weight: Double!
    var array: [AnyObject]?
    var dictionary: [String : AnyObject] = [:]
    var bestFriend: User?                       // Nested User object
    var friends: [User]?                        // Array of Users
    var birthday: NSDate?

    required init?(_ map: Map){

    }

    // Mappable
    func mapping(map: Map) {
        username    <- map["username"]
        age         <- map["age"]
        weight      <- map["weight"]
        array       <- map["arr"]
        dictionary  <- map["dict"]
        bestFriend  <- map["best_friend"]
        friends     <- map["friends"]
        birthday    <- (map["birthday"], DateTransform())
    }
}

struct Temperature: Mappable {
    var celcius: Double?
    var fahrenheit: Double?

    init?(_ map: Map){

    }

    mutating func mapping(map: Map) {
        celcius     <- map["celcius"]
        fahrenheit  <- map["fahrenheit"]
    }
}

一旦您的类实现了 Mappable,Mapper 类将为您处理其他所有事情

将 JSON 字符串转换为模型对象

let user = Mapper<User>().map(JSONString)

将模型对象转换为 JSON 字符串

let JSONString = Mapper().toJSONString(user, prettyPrint: true)

ObjectMapper 可以映射以下类型组成的类

  • Int
  • Bool
  • Double
  • Float
  • String
  • RawRepresentable(枚举)
  • Array<AnyObject>
  • Dictionary<String, AnyObject>
  • Object<T: Mappable>
  • Array<T: Mappable>
  • Array<Array<T: Mappable>>
  • Set<T: Mappable>
  • Dictionary<String, T: Mappable>
  • Dictionary<String, Array<T: Mappable>>
  • 所有以上的可选类型
  • 以上类型的隐式解包可选类型

易于嵌套对象的映射

ObjectMapper 支持在键内使用点表示法来简化嵌套对象的映射。给定以下 JSON 字符串:

"distance" : {
     "text" : "102 ft",
     "value" : 31
}

您可以像以下这样访问嵌套对象:

func mapping(map: Map){
    distance <- map["distance.value"]
}

您也可以将深度数组对象映射到您的平面属性中

func mapping(map: Map){
    currentEmployerName <- map["employments.0.employer.name"]
}

如果您有一个包含 . 的键,您可以取消以上功能,如下所示

func mapping(map: Map){
    identifier <- map["app.identifier", nested: false]
}

必须字段

为了验证服务器响应,您可以在映射规则规范中放置必须参数。验证使用系统的 assert 函数,这不会影响您的发布性能。

func mapping(map: Map){
    identifier <- map["employment.Carma", required: true]
}

在测试中,将以下代码放在您的 setUp 测试函数中,以验证必须字段:

MapRequiredField.assume = { (condition: Bool, message: String) in
    XCTAssert(condition, message)
}

自定义转换

ObjectMapper 同样支持自定义转换,在映射过程中转换值。要使用转换,只需创建一个元组,包含 map["field_name"] 和右边的 <- 操作符上你选择的转换。

birthday <- (map["birthday"], DateTransform())

上面的转换将普通 JSON Int 值转换为 NSDate 当读取 JSON 时,并将 NSDate 转换为 Int 当将对象转换为 JSON 时。

您可以通过采用并实现 TransformType 协议中的方法轻松创建自己的自定义转换。

public protocol TransformType {
    typealias Object
    typealias JSON

    func transformFromJSON(value: AnyObject?) -> Object?
    func transformToJSON(value: Object?) -> JSON?
}

TransformOf

在许多情况下,您可以使用内置转换类 TransformOf 快速执行所需的转换。 TransformOf 用两种类型和两个闭包初始化。类型定义了转换输入和输出的类型,闭包执行实际的转换。

例如,如果您想将 JSON String 值转换为 Int,可以像下面这样使用 TransformOf

let transform = TransformOf<Int, String>(fromJSON: { (value: String?) -> Int? in 
    // transform value from String? to Int?
    return value?.toInt()
}, toJSON: { (value: Int?) -> String? in
    // transform value from Int? to String?
    if let value = value {
        return String(value)
    }
    return nil
})

id <- (map["id"], transform)

下面提供了上述转换的更紧凑版本。

id <- (map["id"], TransformOf<Int, String>(fromJSON: { $0?.toInt() }, toJSON: { $0.map { String($0) } }))

子类

实现 Mappable 协议的类可以轻松地被继承。当继承 Mappable 类时,请遵循以下结构。

class Base: Mappable {
    var base: String?

    required init?(_ map: Map){

    }

    func mapping(map: Map) {
        base <- map["base"]
    }
}

class Subclass: Base {
    var sub: String?

    required init?(_ map: Map){
        super.init(map)
    }

    override func mapping(map: Map) {
        super.mapping(map)

        sub <- map["sub"]
    }
}

映射不可变属性

注意:这是一个实验性功能。不可变映射并不保证 ObjectMapper 的所有功能都有效。

如果您有一个其属性不可变(let)的类或结构体,并希望使用 ObjectMapper 来映射它,可以使用以下方法。

在可失败初始化方法中,使用 map 对象上的 valueOrFail() 函数为您的属性分配值。一旦所有属性都已设置,检查 isValid 以确定所有属性映射是否成功。如果 isValid 返回 false,返回 nil 以指示初始化失败。

class Model: Mappable {
    let name: String // Non-optional property

    required init?(_ map: Map) {
        name = map["name"].valueOrFail()

        if !map.isValid {
            return nil
        }
    }

    func mapping(map: Map) {
    }
}

if let model = Mapper<Model>().map(JSONString) {
    // Now we have valid model.
} else {
    // Something wrong...
}

ObjectMapper + Alamofire

如果您正在使用 Alamofire 进行网络请求,并希望将响应转换为 Swift 对象,可以使用 AlamofireObjectMapper。它是一个简单的 Alamofire 扩展,使用 ObjectMapper 自动将 JSON 响应数据映射到 Swift 对象。

ObjectMapper + Realm

ObjectMapper 和 Realm 可以一起使用。只需遵循以下类结构,您就能使用 ObjectMapper 生成您的 Realm 模型。

class Model: Object, Mappable {
    dynamic var name = ""

    required convenience init?(_ map: Map) {
        self.init()
    }

    func mapping(map: Map) {
        name <- map["name"]
    }
}

Note: Generating a JSON string of a Realm Object using ObjectMappers' `toJSON` function only works within a Realm write transaction. This is caused because ObjectMapper uses the `inout` flag in its mapping functions (`<-`) which are used both for serializing and deserializing. Realm detects the flag and forces the `toJSON` function to be called within a write block even though the objects are not being modified.

贡献

欢迎贡献👍😃.

在提交任何 Pull Request 之前,请确保您已运行包含测试并保证它们通过。如果您包括新功能,请为它编写测试用例。

ObjectMapper 使用 Nimble 来确保测试成功。它是通过 Carthage 包括的。在 ObjectMapper 根目录下运行以下命令以获取 Nimble 依赖并准备测试环境:

carthage checkout

从现在开始,您应该使用 ObjectMapper.xcworkspace 打开项目,而不是 ObjectMapper.xcodeproj。

安装

ObjectMapper 可以通过将以下行添加到您的 Podfile 来使用 Cocoapods 0.36 (beta) (通过 CocoaPods 框架开发指南)添加到您的项目中:

pod 'ObjectMapper', '~> 0.19'

否则,ObjectMapper 可以作为子模块添加。

  1. 将ObjectMapper添加为子模块,方法是在终端打开,然后cd进入顶级项目目录,并输入命令git submodule add https://github.com/Hearst-DD/ObjectMapper.git
  2. 打开ObjectMapper文件夹,将ObjectMapper.xcodeproj拖到你的app项目文件导航器中。
  3. 在Xcode中,点击蓝色项目图标,然后在侧边栏的“Targets”标题下选择应用程序目标以导航到目标配置窗口。
  4. 确保ObjectMapper.framework的部署目标与应用程序目标的部署目标匹配。
  5. 在窗口顶部的标签栏中,打开“Build Phases”面板。
  6. 展开“Target Dependencies”组,并添加ObjectMapper.framework
  7. 点击面板左上角的+按钮,选择“New Copy Files Phase”,并将新阶段重命名为“Copy Frameworks”,设置“Destination”为“Frameworks”,并添加ObjectMapper.framework