帮酷LOGO
  • 显示原文与译文双语对照的内容
文章标签:Swift  映射  对象  
JSON Object mapping written in Swift, support array deep mapping and iOS 7

  • 源代码名称:ObjectMapper
  • 源代码网址:http://www.github.com/Hearst-DD/ObjectMapper
  • ObjectMapper源代码文档
  • ObjectMapper源代码下载
  • Git URL:
    git://www.github.com/Hearst-DD/ObjectMapper.git
  • Git Clone代码到本地:
    git clone http://www.github.com/Hearst-DD/ObjectMapper
  • Subversion代码到本地:
    $ svn co --depth empty http://www.github.com/Hearst-DD/ObjectMapper
    Checked out revision 1.
    $ cd repo
    $ svn up trunk
  • ObjectMapper

    CocoaPodsCarthage compatibleSwift Package ManagerBuild Status

    ObjectMapper是用 Swift 编写的框架,使你可以轻松地将模型对象( 类和结构) 转换为 JSON 。

    插件功能:
    • 将JSON映射到对象
    • 将对象映射到 JSON
    • 嵌套对象( 单独的,在数组中或者在字典中)
    • 映射过程中的自定义转换
    • 结构支持
    • 不可变支持
    基础

    为了支持映射,类或者结构只需要实现 Mappable 协议,其中包括以下功能:

    init?(map: Map)mutatingfuncmapping(map: Map)

    ObjectMapper使用 <- 运算符来定义每个成员变量如何映射到 JSON 。

    classUser: Mappable {
     var username:String?var age:Int?var weight:Double!var array: [Any]?var dictionary: [String:Any] = [:]
     var bestFriend: User?// Nested User objectvar friends: [User]?// Array of Usersvar birthday: Date?requiredinit?(map: Map) {
     }
     // Mappablefuncmapping(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())
     }
    }structTemperature: Mappable {
     var celsius:Double?var fahrenheit:Double?init?(map: Map) {
     }
     mutatingfuncmapping(map: Map) {
     celsius <- map["celsius"]
     fahrenheit <- map["fahrenheit"]
     }
    }

    一旦类实现 Mappable,ObjectMapper就可以轻松地转换为和从 JSON 。

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

    let user =User(JSONString: JSONString)

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

    let JSONString = user.toJSONString(prettyPrint: true)

    另外,Mapper.swift 类也可以用于完成上述( 它还为其他情况提供了额外的功能):

    // Convert JSON String to Modellet user = Mapper<User>().map(JSONString: JSONString)// Create JSON String from Modellet JSONString =Mapper().toJSONString(user, prettyPrint: true)

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

    • Int
    • Bool
    • Double
    • Float
    • String
    • RawRepresentable ( 枚举)
    • Array<Any>
    • Dictionary<String, Any>
    • Object<T: Mappable>
    • Array<T: Mappable>
    • Array<Array<T: Mappable>>
    • Set<T: Mappable>
    • Dictionary<String, T: Mappable>
    • Dictionary<String, Array<T: Mappable>>
    • 上面所有的Optionals
    • 上面的隐式取消包装的Optionals

    Mappable 协议

    mutating func mapping(map: Map)

    这个函数是所有映射定义都应该去的地方。 解析JSON时,在成功创建对象后执行这里函数。 生成JSON时,对对象调用了唯一的函数。

    init?(map: Map)

    ObjectMapper初始值设定项使用这里failable初始值设定项创建对象。 开发人员可以在对象序列化之前使用它来验证 JSON 。 在函数内返回nil将阻止映射发生。 你可以检查 Map 对象中存储的JSON来执行验证:

    requiredinit?(map: Map){
     // check if a required"name" property exists within the JSON.if map.JSON["name"] ==nil {
     returnnil }
    }

    StaticMappable 协议

    StaticMappableMappable的替代方案。 它为开发人员提供了一个 static 函数,ObjectMapper用于对象初始化而不是 init?(map: Map)

    注意:StaticMappableMappable 一样,是 BaseMappable的子协议,mapping(map: Map) 函数是在这里定义的。

    static func objectForMapping(map: Map) -> BaseMappable?

    ObjectMapper使用这里函数获取用于映射的对象。 开发人员应该返回一个符合 BaseMappable 函数的对象实例。 这里函数也可以用于:

    • 在对象序列化之前验证 JSON
    • 提供用于映射的现有缓存对象
    • 返回另一个类型( 它也符合 BaseMappable )的对象,用于映射。 例如可以检查JSON以推断应该用于映射的对象类型( 请参见 ClassClusterTests.swift 中的示例) 。

    如果需要在扩展中实现 ObjectMapper,则需要选择这里协议而不是 Mappable

    ImmutableMappable 协议

    ImmutableMappable 提供映射不可变属性的能力。 这就是 ImmutableMappableMappable的区别:

    ImmutableMappable可以映射属性 JSON -> 模型模型-> JSON初始化
    let id: Intlet name: String?
    var id: Int!
    var name: String?
    init(map: Map) throws {
     id = try map.value("id")
     name = try? map.value("name")
    }
    mutating func mapping(map: Map) {
     id <- map["id"]
     name <- map["name"]
    }
    func mapping(map: Map) {
     id >>> map["id"]
     name >>> map["name"]
    }
    mutating func mapping(map: Map) {
     id <- map["id"]
     name <- map["name"]
    }
    try User(JSONString: JSONString)
    User(JSONString: JSONString)
    init(map: Map) throws

    这里throwable初始值设定项用于映射给定 Map 中的不可变属性。 每个不可变属性都应该在这个初始值设定项中初始化。

    这里初始值设定项在下列情况下引发错误:

    • Map 无法获得给定键的值
    • Map 无法使用 Transform 转换值

    ImmutableMappable 使用 Map.value(_:using:) 方法从 Map 获取值。 这里方法应与 try 关键字一起使用,因为它是 throwable 。 可以使用 try? 轻松地处理 Optional 属性。

    init(map: Map) throws {
     name =try map.value("name") // throws an error when it fails createdAt =try map.value("createdAt", using: DateTransform()) // throws an error when it fails updatedAt =try? map.value("updatedAt", using: DateTransform()) // optional posts = (try? map.value("posts")) ?? [] // optional + default value}
    mutating func mapping(map: Map)

    这里方法是反向转换执行( 模型到 JSON )的地方。 由于无法使用 <- 操作符映射不可变属性,因此开发人员必须使用 >>> 操作符定义反向转换。

    mutatingfuncmapping(map: Map) {
     name >>> map["name"]
     createdAt >>> (map["createdAt"], DateTransform())
     updatedAt >>> (map["updatedAt"], DateTransform())
     posts >>> map["posts"]
    }
    嵌套对象的简单映射

    ObjectMapper支持关键点内的点表示法,以便轻松映射嵌套对象。 给定以下JSON字符串:

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

    可以按如下方式访问嵌套对象:

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

    嵌套键还支持从 array 访问值。 给定一个与距离 array 有关的JSON响应,可以以按如下方式访问该值:

    distance <- map["distances.0.value"]

    如果有一个包含 .的键,则可以单独禁用上述功能,如下所示:

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

    使用包含 .的嵌套键时,可以通过以下( #629 ) 传递自定义嵌套键分隔符:

    funcmapping(map: Map) {
     appName <- map["com.myapp.info->com.myapp.name", delimiter: "->"]
    }
    自定义转换

    ObjectMapper还支持在映射过程中转换值的自定义转换。 要使用转换,只需使用 map["field_name"] 创建一个元组,并在 <- 操作符的右侧创建选择的转换:

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

    上述转换将 JSON Int值转换为读取JSON的日期,将对象转换为JSON时将日期转换为 Int 。

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

    publicprotocolTransformType {
     associatedtypeObjectassociatedtypeJSONfunctransformFromJSON(_value: Any?) -> Object?functransformToJSON(_value: Object?) -> JSON?}

    TransformOf

    在很多情况下,你可以使用内置的转换类 TransformOf 来快速执行所需的转换。 TransformOf 用两种类型和两个闭包初始化。 这些类型定义转换转换到和从中转换的内容,并且闭包执行实际的转换。

    例如如果要将JSON字符串值转换为 Int,则可以使用 TransformOf,如下所示:

    let transform = TransformOf<Int, String>(fromJSON: { (value: String?) ->Int?in 
     // transform value from String? to Int?returnInt(value!)
    }, toJSON: { (value: Int?) ->String?in// transform value from Int? to String?iflet value = value {
     returnString(value)
     }
     returnnil})
    id <- (map["id"], transform)

    下面是上述更精简的版本:

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

    实现 Mappable 协议的类很容易被子类化。 当子类化可以映射类时,请遵循下面的结构:

    classBase: Mappable {
     var base:String?requiredinit?(map: Map) {
     }
     funcmapping(map: Map) {
     base <- map["base"]
     }
    }classSubclass: Base{
     var sub:String?requiredinit?(map: Map) {
     super.init(map)
     }
     overridefuncmapping(map: Map) {
     super.mapping(map)
     sub <- map["sub"]
     }
    }

    确保子类implemenation调用正确的初始值设定项和映射函数,同时也应用来自超类的映射。

    通用对象

    只要泛型类型也符合 Mappable,ObjectMapper就可以处理具有泛型类型的类。 请参见下面的示例:

    classResult<T: Mappable>: Mappable {
     var result: T?requiredinit?(map: Map){
     }
     funcmapping(map: Map) {
     result <- map["result"]
     }
    }let result = Mapper<Result<User>>().map(JSON)
    映射上下文

    在映射期间传递的Map 对象有一个可选的MapContext 对象,如果需要在映射中传递信息,可以以使用。

    要利用这里特性,只需创建一个实现 MapContext ( 这是一个空协议)的对象,并在初始化过程中将它的传递到 Mapper

    structContext: MapContext {
     var importantMappingInfo ="Info that I need during mapping"}classUser: Mappable {
     var name:String?requiredinit?(map: Map){
     }
     funcmapping(map: Map){
     iflet context = map.contextas? Context {
     // use context to make decisions about mapping }
     }
    }let context =Context()let user = Mapper<User>(context: context).map(JSONString)
    ObjectMapper + Alamofire

    如果你正在使用 Alamofire 网络,并且希望将响应转换为 Swift 对象,则可以使用 AlamofireObjectMapper 。 这个简单的Alamofire扩展使用ObjectMapper自动将JSON响应数据映射到 Swift 对象。

    ObjectMapper + 领域

    ObjectMapper和领域可以一起使用。 只要遵循下面的类结构,你就可以使用ObjectMapper来生成你的领域模型:

    classModel: Object, Mappable {
     dynamicvar name =""requiredconvenienceinit?(map: Map) {
     self.init()
     }
     funcmapping(map: Map) {
     name <- map["name"]
     }
    }

    如果要序列化关联的RealmObjects,则可以使用 ObjectMapper+Realm 。 它是一个简单的领域扩展,可以将任意JSON序列化为领域类的列表。

    要序列化 Swift 字符串,Int,Double和Bool数组,可以使用 objectmapperadditions/realm 。 它将 Swift 类型包装到RealmValues中,可以存储在领域类列表中。

    注意:使用 ObjectMappers toJSON 函数生成领域对象的JSON字符串只在领域写事务中有效。 这是因为ObjectMapper在它的映射函数( <- ) 中使用 inout 标志,这两个标志都用于序列化和反序列化。 领域检测标志并强制在写入块中调用 toJSON 函数,即使这些对象未被修改。

    使用ObjectMapper的项目

    如果你有一个使用of扩展或者提供ObjectMapper工具的项目,请在本节中提交与你项目的链接。

    • 改进错误处理。可能使用 throws
    • 类群集文档

    捐赠非常欢迎



    文章标签:对象  Swift  映射  

    Copyright © 2011 HelpLib All rights reserved.    知识分享协议 京ICP备05059198号-3  |  如果智培  |  酷兔英语