GitHub地址
一、字典转模型
- 创建Test.json文件,将这个文件添加到工程中。为这个json文件加入数据:
{
"name" : "小明",
"age" : 8,
"isMerry" : false,
"tools" : ["炭笔", "尺子", "橡皮擦"],
"pet" : {
"name" : "二哈",
"age" : 2
},
"books" : [
{
"title" : "三国演义",
"author" : "罗贯中"
},
{
"title" : "红楼梦",
"author" : "曹雪芹"
},
{
"title" : "西游记",
"author" : "吴承恩"
}
],
"phone" : {
"brand" : "apple",
"name" : "iphoneX",
"price" : 9999,
"isOld" : false
}
}
extension NSObject {
func setValuesForKeys(_ keyedValues: [String : Any]) {
for (key, value) in keyedValues {
setCustomValue(value, forKey: key)
}
}
private func setCustomValue(_ value: Any?, forKey key: String) {
if let dict = value as? [String : Any] {
if let objClass = getClassWith(key) as? NSObject.Type {
let model = objClass.init()
model.setValuesForKeys(dict)
setValue(model, forKey: key)
return
}
} else if let array = value as? [[String : Any]] {
if let objClass = getClassWith(key, isArray: true) as? NSObject.Type {
var resultArray = [NSObject]()
for dict in array {
let model = objClass.init()
model.setValuesForKeys(dict)
resultArray.append(model)
}
setValue(resultArray, forKey: key)
return
}
}
setValue(value, forKey: key)
}
private func getClassWith(_ key: String, isArray: Bool = false) -> AnyClass? {
let mirror = Mirror(reflecting: self)
let children = mirror.children.filter { (child) -> Bool in
return child.label == key
}
if let value = children.first?.value {
var valueType = "\(Mirror(reflecting: value).subjectType)"
if isArray {
valueType = valueType.replacingOccurrences(of: "Array<", with: "")
valueType = valueType.replacingOccurrences(of: ">", with: "")
}
if let projectName = Bundle.main.infoDictionary?["CFBundleName"] as? String {
return NSClassFromString(projectName + "." + valueType)
}
}
return nil
}
}
class TestModel: NSObject {
@objc var name = ""
@objc var age = 0
@objc var isMerry = false
@objc var tools = [String]()
@objc var pet = [String : Any]()
@objc var books = [Book]()
@objc var phone = Phone()
}
class Book: NSObject {
@objc var title = ""
@objc var author = ""
}
class Phone: NSObject {
@objc var brand = ""
@objc var name = ""
@objc var price = 0
@objc var isOld = false
}
if let path = Bundle.main.path(forResource: "Test", ofType: "json") {
do {
let jsonData = try Data(contentsOf: URL(fileURLWithPath: path), options: .alwaysMapped)
let result = try JSONSerialization.jsonObject(with: jsonData, options: .mutableContainers)
if let dict = result as? [String : Any] {
let model = TestModel()
model.setValuesForKeys(dict)
print(model.name)
print(model.age)
print(model.isMerry)
print("--------")
print(model.tools)
print("--------")
print(model.pet)
for book in model.books {
print("--------")
print(book.title)
print(book.author)
}
print("--------")
print(model.phone.brand)
print(model.phone.name)
print(model.phone.price)
print(model.phone.isOld)
}
} catch {
print(error)
}
}
小明
8
false
--------
["炭笔", "尺子", "橡皮擦"]
--------
["age": 2, "name": 二哈]
--------
三国演义
罗贯中
--------
红楼梦
曹雪芹
--------
西游记
吴承恩
--------
apple
iphoneX
9999
false
if let array = result as? [[String : Any]] {
var resultArray = [TestModel]()
for dict in array {
let model = TestModel()
model.setValuesForKeys(dict)
resultArray.append(model)
}
print(resultArray)
}
// 更省事一点也可以利用泛型把这些封装起来
二、模型转字典
func getDictWith(obj: Any) -> [String : Any] {
var dict = [String : Any]()
let mirror = Mirror(reflecting: obj)
for item in mirror.children {
guard let key = item.label else {
continue
}
let value = item.value
if let array = value as? [Any] {
dict.updateValue(getArrayWith(array: array), forKey: key)
} else if isModelWith(value) {
dict.updateValue(getDictWith(obj: value), forKey: key)
} else {
dict.updateValue(value, forKey: key)
}
}
return dict
}
func getArrayWith(array: [Any]) -> [Any] {
var resultArray = [Any]()
guard let first = array.first else {
return array
}
if isModelWith(first) {
for obj in array {
let dict = getDictWith(obj: obj)
resultArray.append(dict)
}
return resultArray
} else {
return array
}
}
func isModelWith(_ value: Any) -> Bool {
let valueType = "\(Mirror(reflecting: value).subjectType)"
if let projectName = Bundle.main.infoDictionary?["CFBundleName"] as? String {
return NSClassFromString(projectName + "." + valueType) != nil
}
return false
}
// 把刚刚创建的model拿来用
let dict = getDictWith(obj: model)
print(dict)
[
"tools": ["炭笔", "尺子", "橡皮擦"],
"phone": ["name": "iphoneX", "brand": "apple", "isOld": false, "price": 9999],
"books": [["title": "三国演义", "author": "罗贯中"], ["author": "曹雪芹", "title": "红楼梦"], ["author": "吴承恩", "title": "西游记"]],
"pet": ["age": 2, "name": 二哈],
"isMerry": false,
"name": "小明",
"age": 8
]