RBBJSON

Swift Version: 5.2 Swift Package Manager Swift Package Manager Twitter: @DLX

RBBJSON 能够在运行时实现灵活的 JSON 遍历,并提供类似 JSONPath 的查询功能,以便快速进行原型设计。

使用 JSONDecoder 创建一个 RBBJSON 结构体,然后使用 动态成员查找 来遍历它。

let json = try JSONDecoder().decode(RBBJSON.self, from: data)

json.firstName         // RBBJSON.string("John")
json.lastName          // RBBJSON.string("Appleseed")
json.age               // RBBJSON.number(26)
json.invalidKey        // RBBJSON.null
json.phoneNumbers[0]   // RBBJSON.string("+14086065775")

如果您想访问的值与 Swift 定义的属性重名,请使用 String 下标来代替。

json.office.map     // Error: Maps to Sequence.map
json.office["map"]  // RBBJSON.string("https://maps.apple.com/?q=IL1")

要解包 JSON 值,请使用其中一个可失败的初始化器。

String(json.firstName) // "John"
String(json.lastName)  // "Appleseed"
String(json.age)       // nil

Int(json.age)          // 26
Double(json.age)       // 26.0

您还可以使用受 JSONPath 启发的查询语法来查找 JSON 结构内部的嵌套数据。

例如,给定:

{ 
  "store": {
    "book": [ 
      { 
        "category": "reference",
        "author": "Nigel Rees",
        "title": "Sayings of the Century",
        "price": 8.95
      },
      { 
        "category": "fiction",
        "author": "Evelyn Waugh",
        "title": "Sword of Honour",
        "price": 12.99
      },
      { 
        "category": "fiction",
        "author": "Herman Melville",
        "title": "Moby Dick",
        "isbn": "0-553-21311-3",
        "price": 8.99
      },
      { 
        "category": "fiction",
        "author": "J. R. R. Tolkien",
        "title": "The Lord of the Rings",
        "isbn": "0-395-19395-8",
        "price": 22.99
      }
    ],
    "bicycle": {
      "color": "red",
      "price": 19.95
    }
  }
}
JSONPath RBBJSON 结果
$.store.book[*].author json.store.book[any: .child].author 商店中所有书籍的作者。
$..author json[any: .descendantOrSelf].author 所有作者。
$.store.* json.store[any: .child] 商店中的所有物品,包括书籍和一辆红色自行车。
$.store..price json.store[any: .descendantOrSelf].price 商店中的所有价格。
$..book[2] json[any: .descendantOrSelf].book[2] 第二本书。
$..book[-2] json[any: .descendantOrSelf].book[-2] 倒数第二本书。
$..book[0,1], $..book[:2] json[any: .descendantOrSelf].book[0, 1]), json[any: .descendantOrSelf].book[0...1]), json[any: .descendantOrSelf].book[0..<2]) 前两本书。
$..book[?(@.isbn)] json[any: .descendantOrSelf].book[has: \.isbn] 所有具有 ISBN 编号的书籍。
$..book[?(@.price<10)] json.store.book[matches: { $0.price <= 10 }] 所有价格低于 10 的书籍。
$.store["book", "bicycle"]..["price", "author"] json.store["book", "bicycle"][any: .descendantOrSelf]["price", "author"] 每本书或自行车的作者(如果可用)和价格。

一旦使用其中一个高阶选择器查询 JSON 值,表达式的结果类型将是一个惰性的 RBBJSONQuery

json.store.book[0]["title"]     // RBBJSON.string("Sayings of the Century")
json.store.book[0, 1]["title"]  // some RBBJSONQuery

因为 RBBJSONQuery 符合 Sequence 协议,您可以初始化一个 Array 来获取结果,或者使用例如 compactMap

String(json.store.book[0].title)                    // "Sayings of the Century"
json.store.book[0, 1].title.compactMap(String.init) // ["Sayings of the Century", "Sword of Honour"]

String(json.store.book[0]["invalid Property"])                    // nil
json.store.book[0, 1]["invalid Property"].compactMap(String.init) // []