query.js 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. // wrapped by build app
  2. define("dojox/jsonPath/query", ["dijit","dojo","dojox"], function(dijit,dojo,dojox){
  3. dojo.provide("dojox.jsonPath.query");
  4. dojox.jsonPath.query = function(/*Object*/obj, /*String*/expr, /*Object*/arg){
  5. // summaRy
  6. // Perform jsonPath query `expr` on javascript object or json string `obj`
  7. // obj - object || json string to perform query on
  8. // expr - jsonPath expression (string) to be evaluated
  9. // arg - {}special arugments.
  10. // resultType: "VALUE"||"BOTH"||"PATH"} (defaults to value)
  11. // evalType: "RESULT"||"ITEM"} (defaults to ?)
  12. var re = dojox.jsonPath._regularExpressions;
  13. if (!arg){arg={};}
  14. var strs = [];
  15. function _str(i){ return strs[i];}
  16. var acc;
  17. if (arg.resultType == "PATH" && arg.evalType == "RESULT") throw Error("RESULT based evaluation not supported with PATH based results");
  18. var P = {
  19. resultType: arg.resultType || "VALUE",
  20. normalize: function(expr){
  21. var subx = [];
  22. expr = expr.replace(/'([^']|'')*'/g, function(t){return "_str("+(strs.push(eval(t))-1)+")";});
  23. var ll = -1;
  24. while(ll!=subx.length){
  25. ll=subx.length;//TODO: Do expression syntax checking
  26. expr = expr.replace(/(\??\([^\(\)]*\))/g, function($0){return "#"+(subx.push($0)-1);});
  27. }
  28. expr = expr.replace(/[\['](#[0-9]+)[\]']/g,'[$1]')
  29. .replace(/'?\.'?|\['?/g, ";")
  30. .replace(/;;;|;;/g, ";..;")
  31. .replace(/;$|'?\]|'$/g, "");
  32. ll = -1;
  33. while(ll!=expr){
  34. ll=expr;
  35. expr = expr.replace(/#([0-9]+)/g, function($0,$1){return subx[$1];});
  36. }
  37. return expr.split(";");
  38. },
  39. asPaths: function(paths){
  40. for (var j=0;j<paths.length;j++){
  41. var p = "$";
  42. var x= paths[j];
  43. for (var i=1,n=x.length; i<n; i++)
  44. p += /^[0-9*]+$/.test(x[i]) ? ("["+x[i]+"]") : ("['"+x[i]+"']");
  45. paths[j]=p;
  46. }
  47. return paths;
  48. },
  49. exec: function(locs, val, rb){
  50. var path = ['$'];
  51. var result=rb?val:[val];
  52. var paths=[path];
  53. function add(v, p,def){
  54. if (v && v.hasOwnProperty(p) && P.resultType != "VALUE") paths.push(path.concat([p]));
  55. if (def)
  56. result = v[p];
  57. else if (v && v.hasOwnProperty(p))
  58. result.push(v[p]);
  59. }
  60. function desc(v){
  61. result.push(v);
  62. paths.push(path);
  63. P.walk(v,function(i){
  64. if (typeof v[i] ==='object') {
  65. var oldPath = path;
  66. path = path.concat(i);
  67. desc(v[i]);
  68. path = oldPath;
  69. }
  70. });
  71. }
  72. function slice(loc, val){
  73. if (val instanceof Array){
  74. var len=val.length, start=0, end=len, step=1;
  75. loc.replace(/^(-?[0-9]*):(-?[0-9]*):?(-?[0-9]*)$/g, function($0,$1,$2,$3){start=parseInt($1||start);end=parseInt($2||end);step=parseInt($3||step);});
  76. start = (start < 0) ? Math.max(0,start+len) : Math.min(len,start);
  77. end = (end < 0) ? Math.max(0,end+len) : Math.min(len,end);
  78. for (var i=start; i<end; i+=step)
  79. add(val,i);
  80. }
  81. }
  82. function repStr(str){
  83. var i=loc.match(/^_str\(([0-9]+)\)$/);
  84. return i?strs[i[1]]:str;
  85. }
  86. function oper(val){
  87. if (/^\(.*?\)$/.test(loc)) // [(expr)]
  88. add(val, P.eval(loc, val),rb);
  89. else if (loc === "*"){
  90. P.walk(val, rb && val instanceof Array ? // if it is result based, there is no point to just return the same array
  91. function(i){P.walk(val[i],function(j){ add(val[i],j); })} :
  92. function(i){ add(val,i); });
  93. }
  94. else if (loc === "..")
  95. desc(val);
  96. else if (/,/.test(loc)){ // [name1,name2,...]
  97. for (var s=loc.split(/'?,'?/),i=0,n=s.length; i<n; i++)
  98. add(val,repStr(s[i]));
  99. }
  100. else if (/^\?\(.*?\)$/.test(loc)) // [?(expr)]
  101. P.walk(val, function(i){ if (P.eval(loc.replace(/^\?\((.*?)\)$/,"$1"),val[i])) add(val,i); });
  102. else if (/^(-?[0-9]*):(-?[0-9]*):?([0-9]*)$/.test(loc)) // [start:end:step] python slice syntax
  103. slice(loc, val);
  104. else {
  105. loc=repStr(loc);
  106. if (rb && val instanceof Array && !/^[0-9*]+$/.test(loc))
  107. P.walk(val, function(i){ add(val[i], loc)});
  108. else
  109. add(val,loc,rb);
  110. }
  111. }
  112. while (locs.length){
  113. var loc = locs.shift();
  114. if ((val = result) === null || val===undefined) return val;
  115. result = [];
  116. var valPaths = paths;
  117. paths = [];
  118. if (rb)
  119. oper(val)
  120. else
  121. P.walk(val,function(i){path=valPaths[i]||path;oper(val[i])});
  122. }
  123. if (P.resultType == "BOTH"){
  124. paths = P.asPaths(paths);
  125. var newResult = [];
  126. for (var i =0;i <paths.length;i++)
  127. newResult.push({path:paths[i],value:result[i]});
  128. return newResult;
  129. }
  130. return P.resultType == "PATH" ? P.asPaths(paths):result;
  131. },
  132. walk: function(val, f){
  133. if (val instanceof Array){
  134. for (var i=0,n=val.length; i<n; i++)
  135. if (i in val)
  136. f(i);
  137. }
  138. else if (typeof val === "object"){
  139. for (var m in val)
  140. if (val.hasOwnProperty(m))
  141. f(m);
  142. }
  143. },
  144. eval: function(x, _v){
  145. try { return $ && _v && eval(x.replace(/@/g,'_v')); }
  146. catch(e){ throw new SyntaxError("jsonPath: " + e.message + ": " + x.replace(/@/g, "_v").replace(/\^/g, "_a")); }
  147. }
  148. };
  149. var $ = obj;
  150. if (expr && obj){
  151. return P.exec(P.normalize(expr).slice(1), obj, arg.evalType == "RESULT");
  152. }
  153. return false;
  154. };
  155. });