source: Dev/trunk/src/client/dojox/jsonPath/query.js @ 483

Last change on this file since 483 was 483, checked in by hendrikvanantwerpen, 11 years ago

Added Dojo 1.9.3 release.

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