通用 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
。
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!
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"