108 lines
2.8 KiB
Swift
108 lines
2.8 KiB
Swift
import Foundation
|
|
|
|
public extension JSON {
|
|
|
|
/// Return the string value if this is a `.string`, otherwise `nil`
|
|
var stringValue: String? {
|
|
if case .string(let value) = self {
|
|
return value
|
|
}
|
|
return nil
|
|
}
|
|
|
|
/// Return the double value if this is a `.number`, otherwise `nil`
|
|
var doubleValue: Double? {
|
|
if case .number(let value) = self {
|
|
return value
|
|
}
|
|
return nil
|
|
}
|
|
|
|
/// Return the bool value if this is a `.bool`, otherwise `nil`
|
|
var boolValue: Bool? {
|
|
if case .bool(let value) = self {
|
|
return value
|
|
}
|
|
return nil
|
|
}
|
|
|
|
/// Return the object value if this is an `.object`, otherwise `nil`
|
|
var objectValue: [String: JSON]? {
|
|
if case .object(let value) = self {
|
|
return value
|
|
}
|
|
return nil
|
|
}
|
|
|
|
/// Return the array value if this is an `.array`, otherwise `nil`
|
|
var arrayValue: [JSON]? {
|
|
if case .array(let value) = self {
|
|
return value
|
|
}
|
|
return nil
|
|
}
|
|
|
|
/// Return `true` iff this is `.null`
|
|
var isNull: Bool {
|
|
if case .null = self {
|
|
return true
|
|
}
|
|
return false
|
|
}
|
|
|
|
/// If this is an `.array`, return item at index
|
|
///
|
|
/// If this is not an `.array` or the index is out of bounds, returns `nil`.
|
|
subscript(index: Int) -> JSON? {
|
|
if case .array(let arr) = self, arr.indices.contains(index) {
|
|
return arr[index]
|
|
}
|
|
return nil
|
|
}
|
|
|
|
/// If this is an `.object`, return item at key
|
|
subscript(key: String) -> JSON? {
|
|
if case .object(let dict) = self {
|
|
return dict[key]
|
|
}
|
|
return nil
|
|
}
|
|
|
|
/// Dynamic member lookup sugar for string subscripts
|
|
///
|
|
/// This lets you write `json.foo` instead of `json["foo"]`.
|
|
subscript(dynamicMember member: String) -> JSON? {
|
|
return self[member]
|
|
}
|
|
|
|
/// Return the JSON type at the keypath if this is an `.object`, otherwise `nil`
|
|
///
|
|
/// This lets you write `json[keyPath: "foo.bar.jar"]`.
|
|
subscript(keyPath keyPath: String) -> JSON? {
|
|
return queryKeyPath(keyPath.components(separatedBy: "."))
|
|
}
|
|
|
|
func queryKeyPath<T>(_ path: T) -> JSON? where T: Collection, T.Element == String {
|
|
|
|
// Only object values may be subscripted
|
|
guard case .object(let object) = self else {
|
|
return nil
|
|
}
|
|
|
|
// Is the path non-empty?
|
|
guard let head = path.first else {
|
|
return nil
|
|
}
|
|
|
|
// Do we have a value at the required key?
|
|
guard let value = object[head] else {
|
|
return nil
|
|
}
|
|
|
|
let tail = path.dropFirst()
|
|
|
|
return tail.isEmpty ? value : value.queryKeyPath(tail)
|
|
}
|
|
|
|
}
|