pathaction.go 1.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162
  1. package jsonpath
  2. // pathNode is used to construct a trie of paths to be matched
  3. type pathNode struct {
  4. matchOn interface{} // string, or integer
  5. childNodes []pathNode
  6. action DecodeAction
  7. }
  8. // match climbs the trie to find a node that matches the given JSON path.
  9. func (n *pathNode) match(path JsonPath) *pathNode {
  10. var node *pathNode = n
  11. for _, ps := range path {
  12. found := false
  13. for i, n := range node.childNodes {
  14. if n.matchOn == ps {
  15. node = &node.childNodes[i]
  16. found = true
  17. break
  18. } else if _, ok := ps.(int); ok && n.matchOn == AnyIndex {
  19. node = &node.childNodes[i]
  20. found = true
  21. break
  22. }
  23. }
  24. if !found {
  25. return nil
  26. }
  27. }
  28. return node
  29. }
  30. // PathActions represents a collection of DecodeAction functions that should be called at certain path positions
  31. // when scanning the JSON stream. PathActions can be created once and used many times in one or more JSON streams.
  32. type PathActions struct {
  33. node pathNode
  34. }
  35. // DecodeAction handlers are called by the Decoder when scanning objects. See PathActions.Add for more detail.
  36. type DecodeAction func(d *Decoder) error
  37. // Add specifies an action to call on the Decoder when the specified path is encountered.
  38. func (je *PathActions) Add(action DecodeAction, path ...interface{}) {
  39. var node *pathNode = &je.node
  40. for _, ps := range path {
  41. found := false
  42. for i, n := range node.childNodes {
  43. if n.matchOn == ps {
  44. node = &node.childNodes[i]
  45. found = true
  46. break
  47. }
  48. }
  49. if !found {
  50. node.childNodes = append(node.childNodes, pathNode{matchOn: ps})
  51. node = &node.childNodes[len(node.childNodes)-1]
  52. }
  53. }
  54. node.action = action
  55. }