做iOS 開發(fā) 一直用的 OC 收壕, 最近這段時間在研究 Swift ,
做開發(fā)必要的一個輪子 就是 JSON 轉(zhuǎn) Model
OC 剛開始用的MJExtension , 后來發(fā)現(xiàn) YYModel 兩個框架功能都滿足開發(fā)需要的一些功能
開發(fā)也相對簡單何陆,對對碼的 侵入都很小。
Swift 官方推薦 值類型的開發(fā)豹储, 而且優(yōu)點很多贷盲。 就想盲目的用下值類型。
YYModel 和 MJExtension 只支持 class 的JSON 轉(zhuǎn) Model
開始看到的幾個框架 struct剥扣, 想找一個像 上面那兩個一樣代碼侵入少巩剖, 解析傻瓜式 簡單直接的 。
開始找的幾個 都是想下面這個一樣
[ObjectMapper] (https://github.com/IcyButterfly/MappingAce)
代碼侵入嚴(yán)重钠怯,寫解析代碼一大段 佳魔。
個人比較懶, 而且 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"]
}
}
也自己開始寫晦炊, 發(fā)現(xiàn)對底層不太了解鞠鲜。 寫有太大難度 。
在Github上搜索了一下 發(fā)現(xiàn)了個輪子
JSON 轉(zhuǎn) Model MappingAce
聲明 struct 的時候只要 遵守 Mapping
協(xié)議
JSON 轉(zhuǎn) Model 的時候只要一句代碼 就搞定
let user = User(fromDic: dict)
和 YYModel
和 MJExtension
比 只多了一個遵守協(xié)議
雖然功能上沒有這兩個 框架強大 但是開發(fā) 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"]```