Swift struct JSON To Model 框架

做iOS 开发 一直用的 OC , 最近这段时间在研究 Swift ,

做开发必要的一个轮子 就是 JSON 转 Model

OC 刚开始用的MJExtension , 后来发现 YYModel 两个框架功能都满足开发需要的一些功能

开发也相对简单,对对码的 侵入都很小。

Swift 官方推荐 值类型的开发, 而且优点很多。 就想盲目的用下值类型。

YYModel 和 MJExtension 只支持 class 的JSON 转 Model

开始看到的几个框架 struct, 想找一个像 上面那两个一样代码侵入少, 解析傻瓜式 简单直接的 。

开始找的几个 都是想下面这个一样

[ObjectMapper] (https://github.com/IcyButterfly/MappingAce)

代码侵入严重,写解析代码一大段 。
个人比较懒, 而且 map["username"] 这样拼写容易出错

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: Date?

    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 celsius: Double?
    var fahrenheit: Double?

    init?(map: Map) {

    }

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

也自己开始写, 发现对底层不太了解。 写有太大难度 。

在Github上搜索了一下 发现了个轮子

JSON 转 Model MappingAce

声明 struct 的时候只要 遵守 Mapping 协议
JSON 转 Model 的时候只要一句代码 就搞定

let user = User(fromDic: dict)

YYModelMJExtension 比 只多了一个遵守协议
虽然功能上没有这两个 框架强大 但是开发 Swift 是足够了。

下面是引用的MappingAce Github上的例子
对比一下

JSON -> Model

Raw struct


// It is recommend to implement protocol `Mapping`, and just implement `Mapping`, no more works
struct PhoneNumber: Mapping{
    var tel: String
    var type: String
}

let phoneInfo: [String : Any] = [
    "tel": "186xxxxxxxx",
    "type": "work"
]
let phone = PhoneNumber(fromDic: phoneInfo)

print(phone.tel) //"186xxxxxxxx"
print(phone.type) //"work"



// Struct did not implement the `Mapping` protocol
struct PhoneNumber {
    var tel: String
    var type: String
}

let phone = MappingAny(type: PhoneEntity.self, fromDic: phoneInfo)

Nested struct mapping

struct User{
    var age: Int
    var name: String
    var phone: PhoneNumber
}

// if you want your serilized nested struct, just implement the `Mapping` protocol
struct PhoneNumber: Mapping {
    var tel: String
    var type: String
}

let dic: [String : Any] = [
    "age" : 24,
    "name": "Binglin",
    "phone": phoneInfo 
]

let user = MappingAny(type: User.self, fromDic: dic)
Optional property

struct User{
    var age: Int?
    var name: String?
    var phone: PhoneNumber?
}

private struct PhoneNumber: Mapping {
    var tel: String
    var type: String
}

let dic: [String : Any] = [
    "name": "Binglin",
]

let user = MappingAny(type: User.self, fromDic: dic)

XCTAssertEqual(user.age, nil)
XCTAssertEqual(user.name, "Binglin")
XCTAssertEqual(user.phone?.tel, nil)
XCTAssertEqual(user.phone?.type, nil)
Enum

enum type of Int & String is support

// eg: EnumInt
enum Gender: Int, EnumInt{
    case male = 1
    case female = 2
}

struct User: Mapping{
    var gender: Gender
}

let dicGender: [String : Any] = ["gender": 1]
let userMale = User(fromDic: dicGender)

XCTAssertEqual(userMale.gender, Gender.male)
// when enum is string type
enum Gender: String, EnumString{
    case male = "m"
    case female = "f"
}
Struct or class has default property value

protocol: InitMapping (Struct or Class)

// struct
struct User: InitMapping{
    var name: String = "default"
    var age: Int?
}

let dic: [String : Any] = ["age": 14]
let user = User(fromDic: dic)

print(user.name) //"default"
print(user.age)  //14


// class
// need to implement an empty initializer.
class User: NSObject, InitMapping{
    var name: String = "default"
    var age: Int?

    required override init() {}/*required*/
}

let dic: [String : Any] = ["name" : "IB"]
let user = User(fromDic: dic)
Model -> JSON

// for object implement Mapping or InitMapping
struct PhoneNumber: Mapping {
    var tel: String
    var type: String
}

let phone = PhoneNumber(tel: "186xxxxxxxx", type: "work")
let toDic = phone.toDictionary()
print(toDic) // ["type": "work", "tel": "186xxxxxxxx"]


// for object do not implement Mapping or InitMapping
// just implement protocol Serializable
struct PhoneNumber: `Serializable` {
    var tel: String
    var type: String
}

let phone = PhoneNumber(tel: "186xxxxxxxx", type: "work")
let toDic = phone.toDictionary()
print(toDic) // ["type": "work", "tel": "186xxxxxxxx"]```

你可能感兴趣的:(Swift struct JSON To Model 框架)