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

我们知道苹果从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;
}

时间: 2024-08-02 14:27:47

Swift使用反射将自定义对象数据序列化成JSON数据的相关文章

以读取博客园随笔备份为例 将xml 序列化成json,再序列化成对象

本文转载:本文转载:http://www.cnblogs.com/codealone/archive/2013/04/14/3020161.html 在线JOSN编辑器http://tools.jb51.net/tools/json/json_editor.htm 非常强大! 资源下载:http://files.cnblogs.com/codealone/ConsoleApplication2.zip Json查看工具:http://files.cnblogs.com/codealone/Jso

views py-Django model,QuerySet 序列化成json报错

问题描述 Django model,QuerySet 序列化成json报错 运行django的views.py中的代码报错如下: 'MetaDict' object has no attribute 'concrete_model' 出错的代码行是:hall_list_data = serializers.serialize("json", clientcase.objects.filter(category="hall")) 我的models.py中定义的模型如下

jQuery Ajax和getJSON获取后台普通json数据和层级json数据用法分析_jquery

本文实例讲述了jQuery Ajax和getJSON获取后台普通json数据和层级json数据用法.分享给大家供大家参考,具体如下: 运行效果截图如下: 具体代码如下: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="h

对象-nodejs获取一个json数据,但是我无法求出json里面数组的长度

问题描述 nodejs获取一个json数据,但是我无法求出json里面数组的长度 上送的json如下: var test1 ={ "ENNAME": "text", "CHNAME": "哈哈哈", "SYSNAME": 1, "APPNAME": 2, "DBTYPE": 3, "ELETYPE": 4, "ELESIZE":

关于自定义标签向页面输出JSON数据的问题

问题描述 我写了一个自定义标签,这个标签主要是向页面写入JSON数据流,那我怎么利用JQuery获取到这个JSON数据了.?谢谢各位老大解答一下. 解决方案 <div id="tg" style="display:none;"><taglib bean="..."></taglib><div>var content = $("#tg").text();解决方案二:老蔡已经说的很明

详解JSON1:使用TSQL查询数据和更新JSON数据_json

JSON是一个非常流行的,用于数据交换的数据格式,主要用于Web和移动应用程序中.JSON 使用键/值对(Key:Value pair)存储数据,并且表示嵌套键值对和数组两种复杂数据类型,仅仅使用逗号(引用Key)和中括号(引用数组元素),就能路由到指定的属性或成员,使用简单,功能强大.在SQL Server 2016版本中支持JSON格式,使用Unicode字符类型表示JSON数据,并能对JSON数据进行验证,查询和修改.推荐一款JSON验证和格式化的工具:json formatter. 一,

json数据-AFNetworking POST JSON数据

问题描述 AFNetworking POST JSON数据 用AFNetworking怎么POST一个JSON数据给服务器 解决方案 我是菜鸟 求详细代码 在线等

我的Android进阶之旅------&amp;gt;解决Jackson、Gson解析Json数据时,Json数据中的Key为Java关键字时解析为null的问题

1.问题描述 首先,需要解析的Json数据类似于下面的格式,但是包含了Java关键字abstract: { ret: 0, msg: "normal return.", news: [ { id: "NEW2016062800875700", from: "腾讯新闻客户端", qqnews_download_url: "http://inews.qq.com/m?refer=openapi_for_xiaotiancai",

FormData 数据转化为 json 数据

两种方法 <!-- 实例:将 FormData 转化为 json --> <meta charset="utf-8"/> <form enctype='application/json' method="post"> <label>用户:</label> <input type="text" name="user"></br> <labe