弗雷迪

Freddy 是由 Big Nerd Ranch 维护的 JSON 解析库。它有三个主要好处:

  1. 类型安全:帮助你以防止运行时崩溃的方式发送和接收 JSON。

  2. 惯用语:利用 Swift 的泛型,枚举和功能特性,无需复杂的文档或神奇的自定义运算符。

  3. 错误处理:为常见的 JSON 错误提供信息性错误信息。

示例 JSON 数据

让我们定义一些示例 JSON 数据以用于这些示例。

{
  "success": true,
  "people": [
    {
      "name": "Matt Mathias",
      "age": 32,
      "spouse": true
    },
    {
      "name": "Sergeant Pepper",
      "age": 25,
      "spouse": false
    }
  ],
  "jobs": [
    "teacher",
    "judge"
  ],
  "states": {
    "Georgia": [
      30301,
      30302,
      30303
    ],
    "Wisconsin": [
      53000,
      53001
    ]
  }
}
let jsonString = "{\"success\": true, \"people\": [{\"name\": \"Matt Mathias\",\"age\": 32,\"spouse\": true},{\"name\": \"Sergeant Pepper\",\"age\": 25,\"spouse\": false}],\"jobs\": [\"teacher\",\"judge\"],\"states\": {\"Georgia\": [30301,30302,30303],\"Wisconsin\": [53000,53001]}}"
let jsonData = jsonString.dataUsingEncoding(NSUTF8StringEncoding)!

反序列化原始数据

要反序列化数据,我们初始化 JSON 对象然后访问特定键。

do {
    let json = try JSON(data: jsonData)
    let success = try json.bool("success")
} catch {
    // do something with the error
}

我们来这里是因为访问关键 successjson 可能会失败 - 它可能不存在,或者值可能不是布尔值。

我们还可以指定访问嵌套在 JSON 结构中的元素的路径。该路径是以逗号分隔的键和索引列表,用于描述感兴趣的值的路径。

do {
    let json = try JSON(data: jsonData)
    let georgiaZipCodes = try json.array("states", "Georgia")
    let firstPersonName = try json.string("people", 0, "name")
} catch {
    // do something with the error
}

直接反序列化模型

JSON 可以直接解析为实现 JSONDecodable 协议的模型类。

public struct Person {
    public let name: String
    public let age: Int
    public let spouse: Bool
}

extension Person: JSONDecodable {
    public init(json: JSON) throws {
        name = try json.string("name")
        age = try json.int("age")
        spouse = try json.bool("spouse")
    }
}

do {
    let json = try JSON(data: jsonData)
    let people = try json.arrayOf("people", type: Person.self)
} catch {
    // do something with the error
}

序列化原始数据

任何 JSON 值都可以直接序列化到 NSData

let success = JSON.Bool(false)
let data: NSData = try success.serialize()

直接序列化模型

任何实现 JSONEncodable 协议的模型类都可以直接序列化到 NSData

extension Person: JSONEncodable {
    public func toJSON() -> JSON {
        return .Dictionary([
            "name": .String(name),
            "age": .Int(age),
            "spouse": .Bool(spouse)
        ])
    }
}

let newPerson = Person(name: "Glenn", age: 23, spouse: true)
let data: NSData = try newPerson.toJSON().serialize()