How to easily parse deep json in Swift

Issue #414

Codable is awesome, but sometimes we just need to quickly get value in a deepy nested JSON. In the same way I did for Dart How to resolve deep json object in Dart, let’s make that in Swift.

See https://github.com/onmyway133/Omnia/blob/master/Sources/Shared/JSON.swift

1
2
3
4
5
6
7
8
9
10
11
12
13
public func resolve<T>(_ jsonDictionary: [String: Any], keyPath: String) -> T? {
var current: Any? = jsonDictionary

keyPath.split(separator: ".").forEach { component in
if let maybeInt = Int(component), let array = current as? Array<Any> {
current = array[maybeInt]
} else if let dictionary = current as? JSONDictionary {
current = dictionary[String(component)]
}
}

return current as? T
}

So we can just resolve via key path

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
class JSONTests: XCTestCase {
func test() {
let json: [String: Any] = [
"outside": [
"object": [
"number": 1,
"text": "hello"
],
"arrayOfObjects": [
[
"number": 2,
"text": "two"
],
[
"number": 3,
"text": "three"
]
],
"arrayOfArrays": [
[
"one", "two", "three", "four"
],
[
"five", "six", "seven"
]
]
]
]

XCTAssertEqual(resolve(json, keyPath: "outside.object.number"), 1)
XCTAssertEqual(resolve(json, keyPath: "outside.object.text"), "hello")
XCTAssertEqual(resolve(json, keyPath: "outside.arrayOfObjects.1.number"), 3)
XCTAssertEqual(resolve(json, keyPath: "outside.arrayOfArrays.1.1"), "six")
}
}

Comments