jsonFieldExpressionParser.pegjs 3.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. /**
  2. * Parser for parsing field expressions.
  3. *
  4. * Syntax: <column reference>[:<json field reference>]
  5. *
  6. * e.g. `Person.jsonColumnName:details.names[1]` would refer to value `'Second'`
  7. * in column `Person.jsonColumnName` which has
  8. * `{ details: { names: ['First', 'Second', 'Last'] } }` object stored in it.
  9. *
  10. * First part <column reference> is compatible with column references used in
  11. * knex e.g. "MyFancyTable.tributeToThBestColumnNameEver".
  12. *
  13. * Second part describes a path to an attribute inside the referred column.
  14. * It is optional and it always starts with colon which follows directly with
  15. * first path element. e.g. `Table.jsonObjectColumnName:jsonFieldName` or
  16. * `Table.jsonArrayColumn:[321]`.
  17. *
  18. * Syntax supports `[<key or index>]` and `.<key or index>` flavors of reference
  19. * to json keys / array indexes:
  20. *
  21. * e.g. both `Table.myColumn:[1][3]` and `Table.myColumn:1.3` would access correctly
  22. * both of the following objects `[null, [null,null,null, "I was accessed"]]` and
  23. * `{ "1": { "3" : "I was accessed" } }`
  24. *
  25. * Caveats when using special characters in keys:
  26. *
  27. * 1. `objectColumn.key` This is the most common syntax, good if you are
  28. * not using dots or square brackets `[]` in your json object key name.
  29. * 2. Keys containing dots `objectColumn:[keywith.dots]` Column `{ "keywith.dots" : "I was referred" }`
  30. * 3. Keys containing square brackets `column['[]']` `{ "[]" : "This is getting ridiculous..." }`
  31. * 4. Keys containing square brackets and quotes
  32. * `objectColumn:['Double."Quote".[]']` and `objectColumn:["Sinlge.'Quote'.[]"]`
  33. * Column `{ "Double.\"Quote\".[]" : "I was referred", "Sinlge.'Quote'.[]" : "Mee too!" }`
  34. * 99. Keys containing dots, square brackets, single quotes and double quotes in one json key is
  35. * not currently supported
  36. *
  37. * For compiling this to parser run `pegjs JsonFieldExpressionParser.pegjs` which generates
  38. * the `JsonFieldExpressionParser.js`
  39. *
  40. * For development there is nice page for interactively hacking parser code
  41. * http://pegjs.org/online
  42. */
  43. start =
  44. column:stringWithoutColon
  45. refs:(':'
  46. (bracketIndexRef / bracketStringRef / colonReference)
  47. (bracketIndexRef / bracketStringRef / dotReference)*
  48. )?
  49. {
  50. var access = [];
  51. if (refs) {
  52. var firstAccess = refs[1];
  53. access = refs[2];
  54. access.unshift(firstAccess);
  55. }
  56. return { columnName: column, access: access };
  57. }
  58. bracketStringRef =
  59. '['
  60. key:(
  61. '"' stringWithoutDoubleQuotes '"' /
  62. "'" stringWithoutSingleQuotes "'" /
  63. stringWithoutSquareBrackets
  64. )
  65. ']'
  66. { return { type: 'object', ref: Array.isArray(key) ? key[1] : key }; }
  67. bracketIndexRef =
  68. '[' index:integer ']'
  69. { return { type: 'array', ref: parseInt(index, 10) }; }
  70. colonReference =
  71. key:stringWithoutSquareBracketsOrDots
  72. { return { type: 'object', ref: key }; }
  73. dotReference =
  74. '.' key:stringWithoutSquareBracketsOrDots
  75. { return { type: 'object', ref: key }; }
  76. stringWithoutSquareBrackets =
  77. chars:([^\x5D\x5B])+ { return chars.join(""); }
  78. stringWithoutColon =
  79. chars:([^:])+ { return chars.join(""); }
  80. stringWithoutDoubleQuotes =
  81. chars:([^"])+ { return chars.join(""); }
  82. stringWithoutSingleQuotes =
  83. chars:([^'])+ { return chars.join(""); }
  84. stringWithoutSquareBracketsOrDots =
  85. chars:([^.\x5D\x5B])+ { return chars.join(""); }
  86. integer = digits:[0-9]+ { return digits.join(""); }