Mappable 1.5.0

Mappable 1.5.0

Leave 维护。



Mappable 1.5.0

  • leavez

Mappable

Swift Swift Package Manager Build Status Codecov branch

Mappable 是一个轻量级、灵活、易于使用的框架,用于将 JSON 转换为模型,特别优化了不变属性初始化。

struct Flight: Mappable {
    let number: String
    let time: Date
    
    init(map: Mapper) throws {

        // with the help of @dynamicMemberLookup feature
        number = try map.id()
        time   = try map.time()

        // or use the old way
        // number = try map.from("id")
        // time   = try map.from("time")
    }
}
// Flight(JSONString: json)

还提供 xcode 插件 以生成自动实现。

特性

  • 仅通过指定映射关系来将 JSON 转换为对象
  • 针对不可变和可选优化
  • 灵活:便于与手动初始化混合
  • 兼容类型转换:例如,整数属性可以使用字符串值初始化
  • 支持键路径

为什么还需要另一个?

大多数 JSON 到模型库无法很好地处理不可变属性初始化。它们需要使用 var 声明属性并具有可空类型,这破坏了 Swift 的简洁,并导致编写出糟糕的代码。Mappable 就是为了解决这个问题而生。

优点 缺点
Codable - Swift 中的原生
- 自动(无需映射关系)
- 支持双向转换
- 不可灵活
- 不支持继承类
HandyJSON - 自动(无需映射关系)
- 支持双向转换
不支持不可变属性
ObjectMapper 双向转换 - 不可变属性支持较弱*
- 多种模式会导致混乱
- 支持某些类型组合的缺失。
SwiftyJSON 不是 JSON 对象转换器。
它仅是一个处理 JSON 数据的便捷工具。

* 1) 不能方便地处理可选。2) 不支持兼容类型转换,这会导致整个对象在 JSON 中出现小的格式错误。

Mappable 高度借鉴了 ObjectMapper。您可以将 Mappable 视为 ObjectMapper 中 ImmutableMappable 的改进版本。

使用方法

基础知识

要支持映射,类型应该实现 Mappable 协议,这个协议只包含一个初始化方法

class Country: Mappable {
    let name: String
    let cities: [City]   // struct City: Mappable { ... }
    let atContinent: Continent // enum Continent: Mappable { ... }
    
    required init(map: Mapper) throws {
        name        = try map.from("name")
        cities      = try map.from("city")
        atContinent = try map.from("location.continent")
    }
}

您只需编写映射关系:一个属性的键路径。尽管这些行只是普通的赋值语句,但不需要指定类型,所以可以将这些行视为映射关系的特殊表示。 (您可以将该行读作“尝试 (从) 将 (值) 映射到 XXX”)😆 )

然后您可以初始化对象如下

// NOTE: these initializer throw errors, you should do error handling
let c = try Country(JSON: jsonDict)
let d = try? Country(JSONString: jsonString)

支持的类型

  • 原始类型: IntDoubleStringBoolURLDate ...
  • 容器类型: ArrayDictionarySet
  • 可选类型
  • 枚举、结构体、对象
  • 以上类型的任意组合

默认值

// just use `??`
cities = try map.from("city") ?? []

可选处理

Optional 类型的值即使 JSON 中没有对应的数据或日期格式错误,也不会抛出错误。在这种情况下,将分配一个 nil 值。

如果您将属性声明为可选的,这可能会意味着该数据在 JSON 中不是严格必需的。因此,如果实际上没有数据,您希望获取一个 nil 值。

struct User: Mappable {
    let ID: String
    let summary: String?
    
    init(map: Mapper) throws {
        ID      = try map.from("id")
        summary = try map.from("summary")
    }
}
let json = ["id": "a123"]
let user = try! User(JSONObject: json) // It won't crash.

兼容类型转换

从下面转换
整型,双精度浮点数,单精度浮点数,CGFloat 字符串
布尔值 整型,"true","True","TRUE","YES","false","False","FALSE","NO","0","1"
字符串 整型,NSNumber
URL 字符串
日期 从1970年1月1日开始的秒数,格式为字符串(例如:2016-06-13T16:00:00+00:00

更多详情请参考此处

自定义转换

初始化器中的内容只是普通的赋值,因此你可以对数据进行任何操作。使用map.getRootValue()map.getValue(keyPath:)来获取原始JSON值并执行所需的操作。

为了方便进行日期转换,在Mapper中也有options属性来设置自定义日期策略。(更复杂的示例 在此

枚举

符合RawRepresentable的枚举有一个默认的Mappable实现。您只需在枚举类型上声明符合Mappable,然后它就会工作。

对于有关联值的枚举,您可以手动实现。

enum EnumWithValues: Mappable {
    case a(Int)
    case b(String)
    
    init(map: Mapper) throws {
        // It could be initialized with a json date like:
        // {"type": "a", value: 123}
        let value = try map.getValue("type", as: String.self)
        switch value {
        case "a":
            self = .a(try map.from("value"))
        case "b":
            self = .b(try map.from("value"))
        default:
            throw ErrorType.JSONStructureNotMatchDesired(value, "string a/b")
        }
    }
}

类继承

class ChildModel: BaseModel {
    let b : Int
    required init(map: Mapper) throws {
        b = try map.from("b")
        try super.init(map: map)
    }
}

嵌套键名路径

使用键名路径"AAA.BBB"在JSON中映射多级路径值

// let json = """ {"AAA": {"BBB": 1}} """
b = try map.from("AAA.BBB")

// use `n` to get a n-th value in array
// let json = """ {"AAA": [11,22,33]} """
b = try map.from("AAA.`2`") // b = 33

如果普通的键名自然包含.,您可以使用如map.from("a.file", keyPathIsNested: false),将此键名作为一个单级路径处理。

安装

  • 适用于Swift 5及4.2:v1.3+
  • 适用于Swift 4.1及以下:v1.2.2

Cocoapods

pod 'Mappable'

Swift 包管理器

.Package(url: "https://github.com/leavez/Mappable.git", from: "1.5.0"),

Carthage

github "leavez/Mappable"

许可协议

Mappable 在 MIT 许可下可用。有关更多信息,请参阅 LICENSE 文件。