iOS JSON序列化/反序列化哪家强?

在iOS开发中,选择合适的JSON序列化/反序列化库至关重要。相较于Java的Gson和fastjson,Swift有更多选择,如ObjectMapper、AlamofireObjectMapper、HandyJSON、SwiftyJSON和MJExtension。本文分析了这些库的特点和问题,例如ObjectMapper的映射函数复杂,HandyJSON的易用性,SwiftyJSON仅支持解析,以及MJExtension的Optional处理和维护问题。最后推荐使用HandyJSON,因为它简洁易用且能满足模型转换需求,并保持活跃更新。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

       如果是Java开发者, 只有2个选择Gson或者fastjson。

       如果是Swift开发者, 那么就有5个选择:ObjectMapper、AlamofireObjectMapper、HandyJSON、SwiftyJSON和MJExtension。 到底用哪个抓狂?  

       其实我们对json三方库有2个基本要求:

1、 json和model互相转换(Android Studio有Gson format插件,但Xcode没有类似功能)

2、 因为服务端大多数使用Java语言编写, 所以json里可能有null,但是Swift语言的空是用nil表示, 我们希望三方库能正确处理空值情况(对象Optional类型)。


先看ObjectMapper : Model类必须实现Mappable协议,即实现init和mapping函数; 适合跟Alamofire配合。但是mapping函数过于臃肿耗时,如果有插件生成还可以。

   class User: Mappable {
        var name: String?
        var age: Int?
        
        init() {
            
        }
        
        required init?(map: Map) {
            
        }
        
        func mapping(map: Map) {
            name  <-  map["username"]
            age   <-  map["age"]
        }
    }
            let user = User()
            user.age = 1
            user.name = nil
            let json = user.toJSONString()
            print(json!)
            
            let user2 = User(JSONString: "{\"name\":null, \"age\":1}")   //模拟服务器响应
            print("\(String(describing: user2?.name)) \(user2?.age ?? 2)")

结果: ["age": 1] 

            nil 1


再看HandyJSON, 写起来比较方便,类和结构体要求继承于HandyJSON、枚举要继承于HandyJSONEnum。

   class Animal: HandyJSON {
        var name: String?
        var age: Int?
        
        required init() {
            
        }
    }
            let animal = Animal()
            animal.age = 1
            let json = animal.toJSONString()
            print(json!)
            
             let object = Animal.deserialize(from: "{\"name\":null, \"age\":1}")   //模拟服务器响应
            print("\(object!.name) \(object!.age) ")

{"age":1}

nil Optional(1) 

比ObjectMapper使用上要简单, 不用写mapping函数那么多代码了。


SwiftyJSON: 取字段值使用比较方便, 但是然并卵? SwiftyJSON不支持转Model, 如果你只是想要解析某几个字段,那么SwiftyJSON是不二选择, 而且适用于Alamofire。

            let original: JSON = [  //构造函数JSON(data: Data)适用于网络响应,即在Alamofire使用
                "first_name": "John",
                "age": 20,
                "skills": ["Coding", "Reading"],
                "address": [
                    "street": "Front St",
                    "zip": "12345",
                ]
            ]
            
            //print(original["address","street"])   //嵌套取值很方便,使用逗号或方框分隔
            print(original["address"]["street"])
            print(original["nocolumn"]["key"])     //乱写的值,即使键错误也不会报错

输出:

Front St      //找到了嵌套的key

null          //没找到key时输出null


OC版本的MJExtension,它的坑在于无法解析Optional Int, 而且如果json里有这个键值的话其它字段也无法解析。

  class People: NSObject {
        var name: String?
        var age: Int?   //请注意:MJExtension不能解析Optional Int类型
    }

            let people = People()
            people.age = 1;
            people.name = "zhangsan"
            let json = people.mj_JSONString()
            print(json!)   //序列化后age被抛弃了。。。
            
            let object = People.mj_object(withKeyValues: "{\"name\":\"zhangsan\",\"age\":1}")  //因为有Optional类型age字段,无法解析
    
            print("\(object?.name)\(object?.age)")
输出:

{"name":"zhangsan"}
Optional("zhangsan")nil

完全找不到age参数的影子, 说明MJExtension无法序列化/反序列化整型。

解决办法很简单, 就是赋个默认值, 即将Optional整型变为整型就可以了。

    class People: NSObject {
        var name: String?
        var age = 0  //赋默认值
    }
重新运行后输出:

{"age":1,"name":"zhangsan"}
Optional("zhangsan")Optional(1)
       MJExtension已经很久不维护了, 不建议使用。 


       综上, 推荐使用HandyJSON, 理由是写法简便且能支持json和model互转的需求, 而且一直在更新维护!












评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值