jsonpath.go 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519
  1. // Package jsonpath implements Stefan Goener's JSONPath http://goessner.net/articles/JsonPath/
  2. //
  3. // A jsonpath applies to any JSON decoded data using interface{} when
  4. // decoded with encoding/json (http://golang.org/pkg/encoding/json/) :
  5. //
  6. // var bookstore interface{}
  7. // err := json.Unmarshal(data, &bookstore)
  8. // authors, err := jsonpath.Read(bookstore, "$..authors")
  9. //
  10. // A jsonpath expression can be prepared to be reused multiple times :
  11. //
  12. // allAuthors, err := jsonpath.Prepare("$..authors")
  13. // ...
  14. // var bookstore interface{}
  15. // err = json.Unmarshal(data, &bookstore)
  16. // authors, err := allAuthors(bookstore)
  17. //
  18. // The type of the values returned by the `Read` method or `Prepare`
  19. // functions depends on the jsonpath expression.
  20. //
  21. // Limitations
  22. //
  23. // No support for subexpressions and filters.
  24. // Strings in brackets must use double quotes.
  25. // It cannot operate on JSON decoded struct fields.
  26. //
  27. package jsonpath
  28. import (
  29. "errors"
  30. "fmt"
  31. "strconv"
  32. "strings"
  33. "text/scanner"
  34. )
  35. // Read a path from a decoded JSON array or object ([]interface{} or map[string]interface{})
  36. // and returns the corresponding value or an error.
  37. //
  38. // The returned value type depends on the requested path and the JSON value.
  39. func Read(value interface{}, path string) (interface{}, error) {
  40. filter, err := Prepare(path)
  41. if err != nil {
  42. return nil, err
  43. }
  44. return filter(value)
  45. }
  46. // Prepare will parse the path and return a filter function that can then be applied to decoded JSON values.
  47. func Prepare(path string) (FilterFunc, error) {
  48. p := newScanner(path)
  49. if err := p.parse(); err != nil {
  50. return nil, err
  51. }
  52. return p.prepareFilterFunc(), nil
  53. }
  54. // FilterFunc applies a prepared json path to a JSON decoded value
  55. type FilterFunc func(value interface{}) (interface{}, error)
  56. // short variables
  57. // p: the parser context
  58. // r: root node => @
  59. // c: current node => $
  60. // a: the list of actions to apply next
  61. // v: value
  62. // actionFunc applies a transformation to current value (possibily using root)
  63. // then applies the next action from actions (using next()) to the output of the transformation
  64. type actionFunc func(r, c interface{}, a actions) (interface{}, error)
  65. // a list of action functions to apply one after the other
  66. type actions []actionFunc
  67. // next applies the next action function
  68. func (a actions) next(r, c interface{}) (interface{}, error) {
  69. return a[0](r, c, a[1:])
  70. }
  71. // call applies the next action function without taking it out
  72. func (a actions) call(r, c interface{}) (interface{}, error) {
  73. return a[0](r, c, a)
  74. }
  75. type exprFunc func(r, c interface{}) (interface{}, error)
  76. type parser struct {
  77. scanner scanner.Scanner
  78. path string
  79. actions actions
  80. }
  81. func (p *parser) prepareFilterFunc() FilterFunc {
  82. actions := p.actions
  83. return func(value interface{}) (interface{}, error) {
  84. return actions.next(value, value)
  85. }
  86. }
  87. func newScanner(path string) *parser {
  88. return &parser{path: path}
  89. }
  90. func (p *parser) scan() rune {
  91. return p.scanner.Scan()
  92. }
  93. func (p *parser) text() string {
  94. return p.scanner.TokenText()
  95. }
  96. func (p *parser) column() int {
  97. return p.scanner.Position.Column
  98. }
  99. func (p *parser) peek() rune {
  100. return p.scanner.Peek()
  101. }
  102. func (p *parser) add(action actionFunc) {
  103. p.actions = append(p.actions, action)
  104. }
  105. func (p *parser) parse() error {
  106. p.scanner.Init(strings.NewReader(p.path))
  107. if p.scan() != '$' {
  108. return errors.New("path must start with a '$'")
  109. }
  110. return p.parsePath()
  111. }
  112. func (p *parser) parsePath() (err error) {
  113. for err == nil {
  114. switch p.scan() {
  115. case '.':
  116. p.scanner.Mode = scanner.ScanIdents
  117. switch p.scan() {
  118. case scanner.Ident:
  119. err = p.parseObjAccess()
  120. case '*':
  121. err = p.prepareWildcard()
  122. case '.':
  123. err = p.parseDeep()
  124. default:
  125. err = fmt.Errorf("expected JSON child identifier after '.' at %d", p.column())
  126. }
  127. case '[':
  128. err = p.parseBracket()
  129. case scanner.EOF:
  130. // the end, add a last func that just return current node
  131. p.add(func(r, c interface{}, a actions) (interface{}, error) { return c, nil })
  132. return nil
  133. default:
  134. err = fmt.Errorf("unexcepted token %s at %d", p.text(), p.column())
  135. }
  136. }
  137. return
  138. }
  139. func (p *parser) parseObjAccess() error {
  140. ident := p.text()
  141. column := p.scanner.Position.Column
  142. p.add(func(r, c interface{}, a actions) (interface{}, error) {
  143. obj, ok := c.(map[string]interface{})
  144. if !ok {
  145. return nil, fmt.Errorf("expected JSON object to access child '%s' at %d", ident, column)
  146. }
  147. if c, ok = obj[ident]; !ok {
  148. return nil, fmt.Errorf("child '%s' not found in JSON object at %d", ident, column)
  149. }
  150. return a.next(r, c)
  151. })
  152. return nil
  153. }
  154. func (p *parser) prepareWildcard() error {
  155. p.add(func(r, c interface{}, a actions) (interface{}, error) {
  156. values := []interface{}{}
  157. if obj, ok := c.(map[string]interface{}); ok {
  158. for _, v := range obj {
  159. v, err := a.next(r, v)
  160. if err != nil {
  161. continue
  162. }
  163. values = append(values, v)
  164. }
  165. } else if array, ok := c.([]interface{}); ok {
  166. for _, v := range array {
  167. v, err := a.next(r, v)
  168. if err != nil {
  169. continue
  170. }
  171. values = append(values, v)
  172. }
  173. }
  174. return values, nil
  175. })
  176. return nil
  177. }
  178. func (p *parser) parseDeep() (err error) {
  179. p.add(func(r, c interface{}, a actions) (interface{}, error) {
  180. return recSearch(r, c, a, []interface{}{}), nil
  181. })
  182. p.scanner.Mode = scanner.ScanIdents
  183. switch p.scan() {
  184. case scanner.Ident:
  185. return p.parseObjAccess()
  186. case '*':
  187. p.add(func(r, c interface{}, a actions) (interface{}, error) { return a.next(r, c) })
  188. return nil
  189. case '[':
  190. return p.parseBracket()
  191. case scanner.EOF:
  192. return fmt.Errorf("cannot end with a scan '..' at %d", p.column())
  193. default:
  194. return fmt.Errorf("unexpected token '%s' after deep search '..' at %d", p.text(), p.column())
  195. }
  196. }
  197. // bracket contains filter, wildcard or array access
  198. func (p *parser) parseBracket() error {
  199. if p.peek() == '?' {
  200. return p.parseFilter()
  201. } else if p.peek() == '*' {
  202. p.scan() // eat *
  203. if p.scan() != ']' {
  204. return fmt.Errorf("expected closing bracket after [* at %d", p.column())
  205. }
  206. return p.prepareWildcard()
  207. }
  208. return p.parseArray()
  209. }
  210. // array contains either a union [,,,], a slice [::] or a single element.
  211. // Each element can be an int, a string or an expression.
  212. // TODO optimize map/array access (by detecting the type of indexes)
  213. func (p *parser) parseArray() error {
  214. var indexes []interface{} // string, int or exprFunc
  215. var mode string // slice or union
  216. p.scanner.Mode = scanner.ScanIdents | scanner.ScanStrings | scanner.ScanInts
  217. parse:
  218. for {
  219. // parse value
  220. switch p.scan() {
  221. case scanner.Int:
  222. index, err := strconv.Atoi(p.text())
  223. if err != nil {
  224. return fmt.Errorf("%s at %d", err.Error(), p.column())
  225. }
  226. indexes = append(indexes, index)
  227. case '-':
  228. if p.scan() != scanner.Int {
  229. return fmt.Errorf("expect an int after the minus '-' sign at %d", p.column())
  230. }
  231. index, err := strconv.Atoi(p.text())
  232. if err != nil {
  233. return fmt.Errorf("%s at %d", err.Error(), p.column())
  234. }
  235. indexes = append(indexes, -index)
  236. case scanner.Ident:
  237. indexes = append(indexes, p.text())
  238. case scanner.String:
  239. s, err := strconv.Unquote(p.text())
  240. if err != nil {
  241. return fmt.Errorf("bad string %s at %d", err, p.column())
  242. }
  243. indexes = append(indexes, s)
  244. case '(':
  245. filter, err := p.parseExpression()
  246. if err != nil {
  247. return err
  248. }
  249. indexes = append(indexes, filter)
  250. case ':': // when slice value is ommited
  251. if mode == "" {
  252. mode = "slice"
  253. indexes = append(indexes, 0)
  254. } else if mode == "slice" {
  255. indexes = append(indexes, 0)
  256. } else {
  257. return fmt.Errorf("unexpected ':' after %s at %d", mode, p.column())
  258. }
  259. continue // skip separator parsing, it's done
  260. case ']': // when slice value is ommited
  261. if mode == "slice" {
  262. indexes = append(indexes, 0)
  263. } else if len(indexes) == 0 {
  264. return fmt.Errorf("expected at least one key, index or expression at %d", p.column())
  265. }
  266. break parse
  267. case scanner.EOF:
  268. return fmt.Errorf("unexpected end of path at %d", p.column())
  269. default:
  270. return fmt.Errorf("unexpected token '%s' at %d", p.text(), p.column())
  271. }
  272. // parse separator
  273. switch p.scan() {
  274. case ',':
  275. if mode == "" {
  276. mode = "union"
  277. } else if mode != "union" {
  278. return fmt.Errorf("unexpeted ',' in %s at %d", mode, p.column())
  279. }
  280. case ':':
  281. if mode == "" {
  282. mode = "slice"
  283. } else if mode != "slice" {
  284. return fmt.Errorf("unexpected ':' in %s at %d", mode, p.column())
  285. }
  286. case ']':
  287. break parse
  288. case scanner.EOF:
  289. return fmt.Errorf("unexpected end of path at %d", p.column())
  290. default:
  291. return fmt.Errorf("unexpected token '%s' at %d", p.text(), p.column())
  292. }
  293. }
  294. if mode == "slice" {
  295. if len(indexes) > 3 {
  296. return fmt.Errorf("bad range syntax [start:end:step] at %d", p.column())
  297. }
  298. p.add(prepareSlice(indexes, p.column()))
  299. } else if len(indexes) == 1 {
  300. p.add(prepareIndex(indexes[0], p.column()))
  301. } else {
  302. p.add(prepareUnion(indexes, p.column()))
  303. }
  304. return nil
  305. }
  306. func (p *parser) parseFilter() error {
  307. return errors.New("Filters are not (yet) implemented")
  308. }
  309. func (p *parser) parseExpression() (exprFunc, error) {
  310. return nil, errors.New("Expression are not (yet) implemented")
  311. }
  312. func recSearch(r, c interface{}, a actions, acc []interface{}) []interface{} {
  313. if obj, ok := c.(map[string]interface{}); ok {
  314. for _, c := range obj {
  315. if result, err := a.next(r, c); err == nil {
  316. acc = append(acc, result)
  317. }
  318. acc = recSearch(r, c, a, acc)
  319. }
  320. } else if array, ok := c.([]interface{}); ok {
  321. for _, c := range array {
  322. if result, err := a.next(r, c); err == nil {
  323. acc = append(acc, result)
  324. }
  325. acc = recSearch(r, c, a, acc)
  326. }
  327. }
  328. return acc
  329. }
  330. func prepareIndex(index interface{}, column int) actionFunc {
  331. return func(r, c interface{}, a actions) (interface{}, error) {
  332. if obj, ok := c.(map[string]interface{}); ok {
  333. key, err := indexAsString(index, r, c)
  334. if err != nil {
  335. return nil, err
  336. }
  337. if c, ok = obj[key]; !ok {
  338. return nil, fmt.Errorf("no key '%s' for object at %d", key, column)
  339. }
  340. return a.next(r, c)
  341. } else if array, ok := c.([]interface{}); ok {
  342. index, err := indexAsInt(index, r, c)
  343. if err != nil {
  344. return nil, err
  345. }
  346. if index < 0 || index >= len(array) {
  347. return nil, fmt.Errorf("out of bound array access at %d", column)
  348. }
  349. return a.next(r, array[index])
  350. }
  351. return nil, fmt.Errorf("expected array or object at %d", column)
  352. }
  353. }
  354. func prepareSlice(indexes []interface{}, column int) actionFunc {
  355. return func(r, c interface{}, a actions) (interface{}, error) {
  356. array, ok := c.([]interface{})
  357. if !ok {
  358. return nil, fmt.Errorf("expected JSON array at %d", column)
  359. }
  360. var err error
  361. var start, end, step int
  362. if start, err = indexAsInt(indexes[0], r, c); err != nil {
  363. return nil, err
  364. }
  365. if end, err = indexAsInt(indexes[1], r, c); err != nil {
  366. return nil, err
  367. }
  368. if len(indexes) > 2 {
  369. if step, err = indexAsInt(indexes[2], r, c); err != nil {
  370. return nil, err
  371. }
  372. }
  373. max := len(array)
  374. start = negmax(start, max)
  375. if end == 0 {
  376. end = max
  377. } else {
  378. end = negmax(end, max)
  379. }
  380. if start > end {
  381. return nil, fmt.Errorf("cannot start range at %d and end at %d", start, end)
  382. }
  383. if step == 0 {
  384. step = 1
  385. }
  386. var values []interface{}
  387. if step > 0 {
  388. for i := start; i < end; i += step {
  389. values = append(values, array[i])
  390. }
  391. } else { // reverse order on negative step
  392. for i := end - 1; i >= start; i += step {
  393. values = append(values, array[i])
  394. }
  395. }
  396. return values, nil
  397. }
  398. }
  399. func prepareUnion(indexes []interface{}, column int) actionFunc {
  400. return func(r, c interface{}, a actions) (interface{}, error) {
  401. if obj, ok := c.(map[string]interface{}); ok {
  402. var values []interface{}
  403. for _, index := range indexes {
  404. key, err := indexAsString(index, r, c)
  405. if err != nil {
  406. return nil, err
  407. }
  408. if c, ok = obj[key]; !ok {
  409. return nil, fmt.Errorf("no key '%s' for object at %d", key, column)
  410. }
  411. if c, err = a.next(r, c); err != nil {
  412. return nil, err
  413. }
  414. values = append(values, c)
  415. }
  416. return values, nil
  417. } else if array, ok := c.([]interface{}); ok {
  418. var values []interface{}
  419. for _, index := range indexes {
  420. index, err := indexAsInt(index, r, c)
  421. if err != nil {
  422. return nil, err
  423. }
  424. if index < 0 || index >= len(array) {
  425. return nil, fmt.Errorf("out of bound array access at %d", column)
  426. }
  427. if c, err = a.next(r, array[index]); err != nil {
  428. return nil, err
  429. }
  430. values = append(values, c)
  431. }
  432. return values, nil
  433. }
  434. return nil, fmt.Errorf("expected array or object at %d", column)
  435. }
  436. }
  437. func negmax(n, max int) int {
  438. if n < 0 {
  439. n = max + n
  440. if n < 0 {
  441. n = 0
  442. }
  443. } else if n > max {
  444. return max
  445. }
  446. return n
  447. }
  448. func indexAsInt(index, r, c interface{}) (int, error) {
  449. switch i := index.(type) {
  450. case int:
  451. return i, nil
  452. case exprFunc:
  453. index, err := i(r, c)
  454. if err != nil {
  455. return 0, err
  456. }
  457. switch i := index.(type) {
  458. case int:
  459. return i, nil
  460. default:
  461. return 0, fmt.Errorf("expected expression to return an index for array access")
  462. }
  463. default:
  464. return 0, fmt.Errorf("expected index value (integer or expression returning an integer) for array access")
  465. }
  466. }
  467. func indexAsString(key, r, c interface{}) (string, error) {
  468. switch s := key.(type) {
  469. case string:
  470. return s, nil
  471. case exprFunc:
  472. key, err := s(r, c)
  473. if err != nil {
  474. return "", err
  475. }
  476. switch s := key.(type) {
  477. case string:
  478. return s, nil
  479. default:
  480. return "", fmt.Errorf("expected expression to return a key for object access")
  481. }
  482. default:
  483. return "", fmt.Errorf("expected key value (string or expression returning a string) for object access")
  484. }
  485. }