GenericJSON 2.0.2

GenericJSON 2.0.2

Tomáš ZnamenáčekMingLQ 维护。



  • Tomáš Znamenáček

通用 JSON

Build Status

通用 JSON 使得处理未经格式化的 JSON 字符串变得容易,而不需要创建一个单独的、有良好类型结构的结构。

可编码和未经格式化的 JSON

Swift 4 引入了一种新的 JSON 编码和解码机制,代表为 Codable 协议。这个特性非常好,非常类型安全,意味着不再可能无中生有地解码一个 JSON 字符串,从其中拉取随意的无类型数据。这通常是好事™ – 但当您确实希望随意编码或解码一个 JSON 字符串,而不为它引入一个单独的、有良好类型结构时,您该怎么办呢?例如

// error: heterogeneous collection literal could only be inferred to '[String : Any]';
// add explicit type annotation if this is intentional
let json = [
    "foo": "foo",
    "bar": 1,
]

// Okay then:
let json: [String:Any] = [
    "foo": "foo",
    "bar": 1,
]

// But: fatal error: Dictionary<String, Any> does not conform to Encodable because Any does not conform to Encodable.
let encoded = try JSONEncoder().encode(json)

这样工作得不太好。此外,虽然任意 JSON 值应该支持相等性检查,但 json 值却不能与其他 JSON 值进行比较。这时就需要 JSON 出场。

使用方法

创建一个 JSON 结构

let json: JSON = [
    "foo": "foo",
    "bar": 1,
]

// "{"bar":1,"foo":"foo"}"
let str = try String(data: try JSONEncoder().encode(json), encoding: .utf8)!
let hopefullyTrue = (json == json) // true!

Encodable 对象转换为通用 JSON 结构

struct Player: Codable {
    let name: String
    let swings: Bool
}

let val = try JSON(encodable: Player(name: "Miles", swings: true))
val == [
    "name": "Miles",
    "swings": true,
] // true

查询值

考虑以下 JSON 结构

let json: JSON = [
    "num": 1,
    "str": "baz",
    "bool": true,
    "obj": [
        "foo": "jar",
        "bar": 1,
    ]
]

可以使用可选属性访问器、下标或动态成员下标来查询值

// Property accessors
if let str = json.objectValue?["str"]?.stringValue {  }
if let foo = json.objectValue?["obj"]?.objectValue?["foo"]?.stringValue {  }

// Subscripting
if let str = json["str"]?.stringValue {  }
if let foo = json["obj"]?["foo"]?.stringValue {  }

// Dynamic member subscripting
if let str = json.str?.stringValue {  }
if let foo = json.obj?.foo?.stringValue {  }

您甚至可以使用点分隔的键路径来钻取嵌套结构

let val = json[keyPath: "obj.foo"] // "jar"