jsonpointer.js 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. var hasExcape = /~/
  2. var escapeMatcher = /~[01]/g
  3. function escapeReplacer (m) {
  4. switch (m) {
  5. case '~1': return '/'
  6. case '~0': return '~'
  7. }
  8. throw new Error('Invalid tilde escape: ' + m)
  9. }
  10. function untilde (str) {
  11. if (!hasExcape.test(str)) return str
  12. return str.replace(escapeMatcher, escapeReplacer)
  13. }
  14. function setter (obj, pointer, value) {
  15. var part
  16. var hasNextPart
  17. for (var p = 1, len = pointer.length; p < len;) {
  18. part = untilde(pointer[p++])
  19. hasNextPart = len > p
  20. if (typeof obj[part] === 'undefined') {
  21. // support setting of /-
  22. if (Array.isArray(obj) && part === '-') {
  23. part = obj.length
  24. }
  25. // support nested objects/array when setting values
  26. if (hasNextPart) {
  27. if ((pointer[p] !== '' && pointer[p] < Infinity) || pointer[p] === '-') obj[part] = []
  28. else obj[part] = {}
  29. }
  30. }
  31. if (!hasNextPart) break
  32. obj = obj[part]
  33. }
  34. var oldValue = obj[part]
  35. if (value === undefined) delete obj[part]
  36. else obj[part] = value
  37. return oldValue
  38. }
  39. function compilePointer (pointer) {
  40. if (typeof pointer === 'string') {
  41. pointer = pointer.split('/')
  42. if (pointer[0] === '') return pointer
  43. throw new Error('Invalid JSON pointer.')
  44. } else if (Array.isArray(pointer)) {
  45. return pointer
  46. }
  47. throw new Error('Invalid JSON pointer.')
  48. }
  49. function get (obj, pointer) {
  50. if (typeof obj !== 'object') throw new Error('Invalid input object.')
  51. pointer = compilePointer(pointer)
  52. var len = pointer.length
  53. if (len === 1) return obj
  54. for (var p = 1; p < len;) {
  55. obj = obj[untilde(pointer[p++])]
  56. if (len === p) return obj
  57. if (typeof obj !== 'object') return undefined
  58. }
  59. }
  60. function set (obj, pointer, value) {
  61. if (typeof obj !== 'object') throw new Error('Invalid input object.')
  62. pointer = compilePointer(pointer)
  63. if (pointer.length === 0) throw new Error('Invalid JSON pointer for set.')
  64. return setter(obj, pointer, value)
  65. }
  66. function compile (pointer) {
  67. var compiled = compilePointer(pointer)
  68. return {
  69. get: function (object) {
  70. return get(object, compiled)
  71. },
  72. set: function (object, value) {
  73. return set(object, compiled, value)
  74. }
  75. }
  76. }
  77. exports.get = get
  78. exports.set = set
  79. exports.compile = compile