一聚教程网:一个值得你收藏的教程网站

热门教程

Swift使用反射将自定义对象数据序列化成JSON数据

时间:2022-06-25 23:41:20 编辑:袖梨 来源:一聚教程网

我们知道苹果从IOS5.0后推出了SDK自带的JSON解决方案NSJSONSerialization,这是一个非常好用的JSON生成和解析工具,效率也比其他第三方开源项目高。
但用其生成JSON数据有个限制:只能将Foundation对象转换成JSON。即顶层对象必须是NSArray或者NSDictionary,所有的对象必须是NSString、NSNumber、NSArray、NSDictionary、NSNull的实例。
所以,如果我们想要把自定义类型的数据对象转成JSON数据,NSJSONSerialization就无能为力了。 

1,将自定义对象转成JSON数据的实现原理(不借助第三方库)

(1)首先我们使用反射(Reflection)对自定义类型的数据对象中所有的属性进行递归遍历,生成字典类型的数据并返回。
(2)接着使用NSJSONSerialization就可以把这个字典类型的数据转换成jSON数据了。

2,比如我们自定义一个的联系人类

//用户类
class User {
    var name:String = ""  //姓名
    var nickname:String?  //昵称
    var age:Int?   //年龄
    var emails:[String]?  //邮件地址
    var tels:[Telephone]? //电话
}
 
//电话结构体
struct Telephone {
    var title:String  //电话标题
    var number:String  //电话号码
}

3,JSON串生成的功能实现

(1)首先定义一个叫JSON的协议,并对其扩展,实现协议中定义的两个方法。
toJSONModel():将数据转成可用的JSON模型。
toJSONString():将数据转成JSON字符串(其内部会调用前面的toJSONModel()方法)。
(2)将可选类型(Optional),自定义类(User、TeleTelephone),以及基本数据类型进行扩展,使其遵循JSON协议。
同时对于可选类型还要重写toJSONModel()方法,为的是当可选类型值不存在时返回nil,存在时将其转成具体类型并序列化。

//自定义一个JSON协议
protocol JSON {
    func toJSONModel() -> AnyObject?
    func toJSONString() -> String?
}
 
//扩展协议方法
extension JSON {
    //将数据转成可用的JSON模型
    func toJSONModel() -> AnyObject? {
        let mirror = Mirror(reflecting: self)
        if mirror.children.count > 0  {
            var result: [String:AnyObject] = [:]
            for case let (label?, value) in mirror.children {
                //print("属性:(label)     值:(value)")
                if let jsonValue = value as? JSON {
                    result[label] = jsonValue.toJSONModel()
                }
            }
            
            return result
        }
        return self as? AnyObject
    }
    
    //将数据转成JSON字符串
    func toJSONString() -> String? {
        let jsonModel = self.toJSONModel()
        //利用OC的json库转换成OC的NSData,
        let data : NSData! = try? NSJSONSerialization.dataWithJSONObject(jsonModel!, options: [])
        //NSData转换成NSString打印输出
        let str = NSString(data:data, encoding: NSUTF8StringEncoding)
        return str as String?
    }
}
 
//扩展可选类型,使其遵循JSON协议
extension Optional: JSON {
    //可选类型重写toJSONModel()方法
    func toJSONModel() -> AnyObject? {
        if let x = self {
            if let value = x as? JSON {
                return value.toJSONModel()
            }
        }
        return nil
    }
}
 
//扩展两个自定义类型,使其遵循JSON协议
extension User: JSON { }
extension Telephone: JSON { }
 
//扩展Swift的基本数据类型,使其遵循JSON协议
extension String: JSON { }
extension Int: JSON { }
extension Bool: JSON { }
extension Dictionary: JSON { }
extension Array: JSON { }

4,测试样例

//创建一个User实例对象
let user1 = User()
user1.name = "hangge"
user1.age = 100
user1.emails = ["hangge@hangge.com","system@hangge.com"]
//添加动画
let tel1 = Telephone(title: "手机", number: "123456")
let tel2 = Telephone(title: "公司座机", number: "001-0358")
user1.tels = [tel1, tel2]
 
//输出json字符串
print(user1.toJSONString()!)
看到控制台输出如下信息:
原文:Swift - 使用反射将自定义对象数据序列化成JSON数据

格式化后数据如下:
{
    "tels": {
        "[1]": {
            "number": "001-0358",
            "title": "公司座机"
        },
        "[0]": {
            "number": "123456",
            "title": "手机"
        }
    },
    "age": 100,
    "name": "hangge",
    "emails": {
        "[1]": "system@hangge.com",
        "[0]": "hangge@hangge.com"
    }
}

使用第三方库 - JSONKit 


1,新建桥街头文件Bridging-Header.h,并设置到编译参数里
1 #include "JSONKit.h"
2,将JSONKit的库文件导入到项目中来(JSONKit.h和JSONKit.m)
3,这时编译会发现报错,这是由于JSONKit库不支持Objective-C的自动引用计数功能导致。
需要在Build Phases -> Compile Sources -> JSONKit.m,双击添加Comipler Flag:-fno-objc-arc 。这样就完成了不支持自动引用计数的配置。
 

测试代码:

import UIKit
 
class ViewController: UIViewController {
     
    override func viewDidLoad() {
        super.viewDidLoad()
        testJson()
    }
     
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }
     
    func testJson() {
        //Swift 字典对象
        let user = [
            "uname": "user1",
            "tel": ["mobile": "138", "home": "010"]
        ]
        //使用 JSONKit 转换成为 JSON 字符串
        let jsonstring = (user as NSDictionary).JSONString()
        print(jsonstring);
        //由字符串反解析回字典
        print(jsonstring.objectFromJSONString() as! NSDictionary)
         
        //使用 JSONKit 转换成为 NSData 类型的 JSON 数据
        let jsondata = (user as NSDictionary).JSONData()
        print(jsondata);
        //由NSData 反解析回为字典
        print(jsondata.objectFromJSONData() as! NSDictionary)
    }
}

输出结果:

{"uname":"user1","tel":{"home":"010","mobile":"138"}}
{
    tel =     {
        home = 010;
        mobile = 138;
    };
    uname = user1;
}
<7b22756e 616d6522 3a227573 65723122 2c227465 6c223a7b 22686f6d 65223a22 30313022 2c226d6f 62696c65 223a2231 3338227d 7d>
{
    tel =     {
        home = 010;
        mobile = 138;
    };
    uname = user1;
}

热门栏目