如何使用 SwiftyJSON 解析 JSON

953 阅读4分钟

原文:How to parse JSON using SwiftyJSON - free Swift 5.4 example code and tips

SwiftyJSON 是一个超级简化的 JSON 解析库,它给你的语法比内置的 iOS 库更清晰(是的,甚至比 Codable 中的 JSONEncoder 更清晰),并且是免费的。

你可以从这里下载它 -- 解压你下载的文件,然后在它的 Source 目录中寻找,并将 SwiftyJSON.swift 拖到你的 Xcode 项目中。要使用 SwiftyJSON,你需要把你的 JSON 字符串转换成一个 Data 对象,然后把它送进去进行解析。一旦完成,你只需请求你想要的格式的数据,(这里是最棒的一点)SwiftyJSON 保证会返回一些东西

如果所有东西都是好的,这个 "东西" 将是你的数据。但是如果你请求了错误的东西(要么是打错了,要么是因为你没有正确理解你的 JSON 结构),或者是 JSON 发生了变化,SwiftyJSON 将只是返回一个默认值。

为了让你开始,这里有一些 JSON 的例子:

let json = "{ \"people\": [{ \"firstName\": \"Paul\", \"lastName\": \"Hudson\", \"isAlive\": true }, { \"firstName\": \"Angela\", \"lastName\": \"Merkel\", \"isAlive\": true }, { \"firstName\": \"George\", \"lastName\": \"Washington\", \"isAlive\": false } ] }"

它包含一个有三个人的数组,每个人都有一个 firstName,一个 lastName,和一个 isAlive 的状态。要使用 SwiftyJSON 解析这个数组并打印出所有的名字,下面是代码:

if let data = json.data(using: .utf8) {
    if let json = try? JSON(data: data) {
        for item in json["people"].**arrayValue** {
            print(item["firstName"].**stringValue**)
        }
    }
}

这里是 arrayValuestringValue 属性在起作用:第一个属性返回 people 中的数组,如果 people 元素不存在,则返回一个空数组,第二个属性返回 peoplefirstName 属性,如果没有设置,则返回一个空字符串。因此,无论发生什么情况,这段代码都会工作,这意味着它很容易编写,运行也很安全。

有时 JSON 有相当深的嵌套字典,但这没关系:SwiftyJSON 可以在一次调用中浏览多个层次,如果任何一个层次失败,你仍然会得到你的默认值。例如,如果你有这样的 JSON:

{  
   "metadata":{  
      "responseInfo":{  
         "status":200,
         "developerMessage":"OK",
      }
   }
}

你可能想在继续之前检查状态代码是否为 200。要做到这一点,只需一次性读取 "metaData"、"responseInfo" 和 "status" 的值,并询问 SwiftyJSON 的 intValue - 你会得到正确的数字(200)或 0,如果这些值都不存在。就像这样:

if json["metadata"]["responseInfo"]["status"].intValue == 200 {
    // we're OK to parse!
}

如何使用 SwiftyJSON 解析 JSON @Mark, 20180117

How to parse JSON with SwiftyJson

使用 JSON 作为客户端和服务器之间的通信媒介是很常见的。然而,Swift 并没有提供一种友好的编码方式来将 JSON 转换为自定义对象。

让我们以下面这个 JSON 为例。

这个例子有 StringDictionaryIntBoolArray 类型:

{
    "name": "joe",       
    "birthday" : {       
        "year": 1990,    
        "month": 1,
        "day": 1
    },
    "isActive": true,    
    "contacts": [        
        {
            "type": "email",
            "value": "joe@test.com"
        },
        {
            "type": "phone",
            "value": "123456"
        }
    ]
}

如果我们需要从上述 JSON 中获取所有的值,我们需要使用 JSONerialization 来转换值:

if let userDict = try? JSONSerialization.jsonObject(with: data, options: .allowFragments) as? [String: Any] {
    if let name = userDict["name"] as? String {
        // get name
    }
    if let birthdayDict = userDict["birthday"] as? [String: Any] {
        if let year = birthdayDict["year"] as? Int {
            // get the birthday year
        }
        // get birthday month and day
    }
    if let isActive = userDict["isActive"] as? Bool {
        // get isActive
    }
    if let contactArr = userDict["contacts"] as? [[String: Any]] {
        for contactDict in contactArr {
            if let type = contactDict["type"] as? String {
                // get contact type
            }
            if let value = contactDict["value"] as? String {
                // get contact type
            }
        }
    }
}

如果 user.json 比较长,比较复杂,那么代码就比较长,读起来就比较困难。那么,我们是否有一个简单的方法来做到这一点?

是的,我们可以使用 SwiftyJSON,这是一个 Swift 框架,它有助于简化代码,提高可读性)。

github.com/SwiftyJSON/… (支持 CocoaPods 或 Carthage 或 Swift Package Manager)

导入该库后,你可以这样写代码:

import SwiftyJson

let userJson = JSON(data: dataFromNetworking)
if let name = userJson["name"].string { 
    // get name 
}

if let year  = userJson["birthday"]["year"].number,
   let month = userJson["birthday"]["month"].number,
   let day   = userJson["birthday"]["day"].number {
    // get birthday year, month, day
}

if let isActive = userJson["isActive"].bool {
    // get isActive
}

if let contactArr = userJson["contacts"].array {
    for contactDict in contactArr {
        if let type = contactDict["type"].string {
            // get type
        }
        if let value = contactDict["value"].string {
            // get value
        }
    }
}

使用 SwiftyJSON 后有 3 个主要的改进:

  1. 使用.string .number .bool 来获取数值(注:这里得到的是可选类型值),而不是使用 as? <type> 将 JSON 中默认的 Any 类型转换为你想要的类型。
  2. 它可以直接获取 dictionary 对象的值,birthdayDict ["birthday"]["year"]
  3. 增加了可读性,并在需要时容易添加 / 删除一个参数

如果你想在使用前检查所有的值,你可以使用 guard let

import SwiftyJson

let userJson = JSON(data: dataFromNetworking)
guard let name = userJson["name"].string else { .. }
guard let year = userJson["birthday"]["year"].number else { .. }
guard let month = userJson["birthday"]["month"].number else { .. }
guard let day = userJson["birthday"]["day"].number else { .. }
guard let isActive = userJson["isActive"].bool else { .. }
guard let contactArr = userJson["contacts"].array else { .. }

// use the value

如果你喜欢这个内容,请喜欢这个帖子。 :)


SwiftyJSON 对应的 JSON 转换为对象 @20191022

iOS SwiftyJSON 对应的JSON 转化为 对象 - 腾讯云开发者社区-腾讯云

swiftyJSON与对象Model的转换 - Sprite is learning

SwiftyJSON: How To Parse JSON with Swift

JSONMappable - Simplify JSON mapping into objects with SwiftyJSON