source: Dev/branches/rest-dojo-ui/client/dojox/jsonPath/query.js @ 256

Last change on this file since 256 was 256, checked in by hendrikvanantwerpen, 13 years ago

Reworked project structure based on REST interaction and Dojo library. As
soon as this is stable, the old jQueryUI branch can be removed (it's
kept for reference).

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