jsonq-js
Version:
JSON Query Javascript Libiary
1,030 lines (1,001 loc) • 28.6 kB
JavaScript
(function(){
function _checkString(arg){
if(arg.constructor==String){
return arg.split(",");
}
return arg
}
function _hasStr(s,str){
return s.indexOf(str)!==-1
}
function _cloneArray(arr) {
var a=new Array();
arr.forEach(function(item){
a.push(_clone(item));
});
return a;
};
function _sortByAttr(arr,a,type, b) {
var c = arr.length;
var d, current;
for (var i = 1; i < c; i++) {
d = i - 1;
current = arr[i];
while (d >= 0 && _compareValue(arr[d][a],current[a],type) ) {
arr[d + 1] = arr[d];
d--
}
arr[d + 1] = current
}
if (type == false||b==false) {
arr.reverse()
}
return arr
};
function _compareValue(a,b,type){
if(_getSortValue(a,type)>_getSortValue(b,type)){
return true;
}
return false;
};
function _getSortValue(value,type){
if(type==undefined||_type(type)=="boolean"){
return value;
}else{
var res=null;
switch(type){
case "date":
if(_type(value)=="date"){
res=value;
}else{
var arr;
if(_hasStr(value,'-')){
arr=value.split("-");
}else{
arr=value.split("/");
}
res=new Date(arr[0],arr[1],arr[2]);
}break;
case "length":res=value.length;break;
case "headLetter":res=value.toLowerCase().charCodeAt(0);break;
case "number":res=value;break;
default:res=value;break;
}
return res;
}
};
function _type(obj){
if(arguments.length==0){
throw new Error("This function need a argument");
}else{
var type=typeof obj;
if(type=="object"){
if(obj===null){
return "null";
}else{
var con = obj.constructor;
switch(con){
case Object:type="json";break;
case Array:type="array";break;
case HTMLCollection:type="htmlcollection";break;
case NodeList:type="nodelist";break;
case FormData:type="formdata";break;
case Error:type="error";break;
case Date:type="date";break;
default:if(_hasStr(con.toString(),'HTML')){
type="htmlelement";
}else{
type="object";
};break;
}
}
}
return type;
}
};
function _clone(obj){
if(obj==undefined){
return null;
}
var type=_type(obj);
if(type=="array"){
return _cloneArray(obj);
}else if(type=="json"||type=="object"){
var a=new Object();
for(var attr in obj){
if(obj[attr]==null||obj[attr]==undefined){
a[attr]=obj[attr];
}else if(_type(obj[attr])=="array"){
a[attr]=_cloneArray(obj[attr]);
}else if(_type(obj[attr])=="json"||_type(obj[attr])=="object"){
a[attr]=_clone(obj[attr]);
}else{
a[attr]=obj[attr];
}
}
return a;
}else if(type=="number"||type=="boolean"||type=="string"||type=="function"){
return obj;
}else{
return obj;
}
};
//var arg=1;
var TYPE={
update:"update",
select:"select",
delete:"delete",
insert:"insert",
add:"add",
remove:"remove",
clear:"clear",
groupBy:"groupBy",
desc:"desc",
asc:"asc",
all:"*"
};
var FUN={
//avg count first last max min
sum:"sum",
count:"count",
avg:"avg",
distinct:"distinct",
first:"first",
last:"last",
max:"max",
min:"min",
array:["sum","count","avg","distinct","first","last","max","min"]
}
function _jqlSetAttrAndValue(data,set){
var attra=[];
var valuea=[];
for(var attr in data){
attra.push(attr);
valuea.push(data[attr]);
}
set.attr(attra);
set.value(valuea);
}
function _jqlSelect(get,set,arg,run){
if(arg==undefined||arg.constructor==Boolean){
if(run===true||arg===true){
return _jqlCheckReturn(get.data(),get);
}
arg=TYPE.all;
}
if(get.canQuery()){
set.type(TYPE.select);
set.attr(_checkString(arg));
return _jqlCheckRun.call(this,run);
}
return this;
};
function _jqlUpdate(get,set,data,value,run){
return _addAndUpdateCom.call(this,get,set,data,value,run,TYPE.update);
};
function _jqlAdd(get,set,data,value,run){
return _addAndUpdateCom.call(this,get,set,data,value,run,TYPE.add);
}
function _addAndUpdateCom(get,set,data,value,run,type){
if(get.canQuery()){
set.type(type);
if(data.constructor==Object){
_jqlSetAttrAndValue(data,set);
run=value;
}else{
set.attr(_checkString(data));
set.value(_checkString(value));
}
return _jqlCheckRun.call(this,value,run);
}
return this;
}
function _jqlRemove(get,set,arg,run){
set.type(TYPE.remove);
if(arg!=undefined&&arg.constructor!=Boolean){
set.attr(_checkString(arg));
return _jqlCheckRun.call(this,run);
}else {
set.attr(TYPE.all);
if(arg.constructor==Boolean){
return _jqlCheckRun.call(this,run);
}
}
return this;
}
function _jqlDelete(get,set,index,run){
set.type(TYPE.delete);
if(index!=undefined&&index.constructor==Number){
set.index(index);
return _jqlCheckRun.call(this,run);
}
return _jqlCheckRun.call(this,index);
}
function _jqlInsert(get,set,a1,a2,a3,a4){//(arg,value,i,run)
set.type(TYPE.insert);
if(a1.constructor==Object){
set.attr(a1);
if(a2!=undefined){
if(a2.constructor==Number){
set.index(a2);
return _jqlCheckRun.call(this,a3);
}else{
return _jqlCheckRun.call(this,a2);
}
}
}else{
set.attr(_checkString(a1));
set.value(_checkString(a2));
if(a3!=undefined){
if(a3.constructor==Number){
set.index(a3);
return _jqlCheckRun.call(this,a4);
}else{
return _jqlCheckRun.call(this,a3);
}
}
}
return this;
}
function _jqlSetCondAttrAndValue(data,set){
var attra=[];
var valuea=[];
for(var attr in data){
attra.push(attr);
valuea.push(data[attr]);
}
set.condAttr(attra);
set.condValue(valuea);
}
function _jqlWhere(get,set,attr,value,run){
if(get.type()===""){
_throw("where:使用where之前必须使用select、update、add、remove、insert、delete方法之一");
}else{
if(attr.constructor==Object){
_jqlSetCondAttrAndValue(attr,set);
run=value;
}else{
if(value!=undefined&&value.constructor==String){
set.condAttr(_checkString(attr));
set.condValue(_checkString(value));
}else{//复杂模式 bool表达式
set.condAttr(attr);
run=value;
}
}
set.cond(true);
return _jqlCheckRun.call(this,value,run);
}
}
function _jqlCheckWhere(index,get,realI){
if(get.cond()){
var data=get.data()[index];
var attr=get.condAttr();
if(get.condValue().length>0){
for(var i=0;i<attr.length;i++){
if(data[attr[i]]!=get.condValue()[i]){
return false;
}
}
}else{//bool表达式
var attrs=_getObjectAttr(data);
eval("var "+attrs);
var $index=index;
var $i=index;
if(realI!=undefined){
$index=realI;
}
for(var i=0;i<attrs.length;i++){
if(_hasStr(attr,attrs[i])){
var item=data[attrs[i]];
if(item==undefined){
_throw("where:"+attrs[i]+"属性不存在");
}else{
eval(attrs[i]+"="+JSON.stringify(item));
}
}
}
return eval(attr);
}
}
return true;
}
function _getObjectAttr(obj){
var arr=[];
for(attr in obj){
arr.push(attr);
}
return arr;
}
function _jqlGroupBy(get,set,attr,run){
if(attr==undefined||attr.constructor!=String){
_throw("groupBy属性参数必须非空且为字符串");
}else{
set.groupAttr(attr);
return _jqlCheckRun.call(this,run);
}
};
function _throw(str){
str=str||"未知异常";
throw new Error(str);
}
function _jqlOrderBy(get,set,attr,order,orderType,run){
if(attr==undefined||attr.constructor!=String){
_throw("orderBy属性参数必须非空且为字符串");
}else{
set.orderAttr(attr);
if(order!=undefined){
if(order.constructor==String){
order=order.toLowerCase();
if(order=="desc"||order=="asc"){
set.order(order);
if(orderType!=undefined&&orderType.constructor==String){
set.orderType(orderType);
}
}else{
set.orderType(order);
}
return _jqlCheckRun.call(this,order,orderType,run);
}
return _jqlCheckRun.call(this,order);
}
return this;
}
};
function _getRunGroupBySelect(obj,sel,as){
if(sel){
if(as[0]==TYPE.all||as[0]==""){
return obj;
}
var d={};
if(as!=TYPE.all&&as.length>0){
as.forEach(function(a){
d[a]=obj[a];
});
}
return d;
}
return obj;
}
function _checkSelectAttr(attr){
for(var i=0;i<attr.length;i++){
if(_hasStr(attr[i],"(")){
return false;
}
}
return true;
}
function _jqlCheckReturn(res,get){
if(get.single()){
return _clone(res[0]);
}
return _clone(res);
}
function _checkRunOrderBy(get,res){
var attr=get.orderAttr();
if(attr!=""){
if(get.order()=="desc"){
_sortByAttr(res,attr,get.orderType(),false);
}else{
_sortByAttr(res,attr,get.orderType());
}
}
return res;
}
function _checkRunGroupBy(get,data){
//avg count count(DISTINCT ) first last max min
//实现函数
var attr=get.groupAttr();
var as=get.attr();
var gres=[];
var vs=[];
var norSel=_checkSelectAttr(as);
if(attr!=""){
data.forEach(function(item){
if(item.hasOwnProperty(attr)){
var index=vs.index(item[attr]);
if(index==-1){
vs.push(item[attr]);
gres.push([_getRunGroupBySelect(item,norSel,as)]);
}else{
gres[index].push(_getRunGroupBySelect(item,norSel,as));
}
}else{
_throw("groupBy:元素中没有"+attr+"属性");
}
});
if(!norSel){
var funs=get.groupFuns();
if(funs.length>0){
var funRes=[];
gres.forEach(function(items){
var newobj={};
var names=[];
funs.forEach(function(fun){
if(fun.fun==undefined){
if(fun.attr!=attr){
_throw(fun.attr+" 没有groupBy");
}else{
newobj[attr]=items[0][attr];
}
}else{
if(fun.name==TYPE.all){
if(fun.fun!=FUN.count){
_throw("* 不能用于"+fun.fun+"方法");
}
fun.name=FUN.count;
}
if(!_hasStr(names,fun.name)){
names.push(fun.name);
}else{
_throw(fun.name+"列名不能相同");
}
if(fun.name==fun.attr){
fun.name=fun.fun;
}
switch(fun.fun){
case FUN.sum:{
newobj[fun.name]=_getGroupAttrArr(items,fun.attr).sum();
};break;
case FUN.count:{
newobj[fun.name]=items.length;
};break;
case FUN.avg:{
newobj[fun.name]=_getGroupAttrArr(items,fun.attr).avg();
};break;
case FUN.first:{
newobj[fun.name]=items.first()[fun.attr];
};break;
case FUN.last:{
newobj[fun.name]=items.last()[fun.attr];
};break;
case FUN.max:{
newobj[fun.name]=_getGroupAttrArr(items,fun.attr).max();
};break;
case FUN.min:{
newobj[fun.name]=_getGroupAttrArr(items,fun.attr).min();
};break;
default:{
newobj[fun.name]=items[0][fun.attr];
};break;
}
}
});
funRes.push(newobj);
});
return funRes;
}
}
return gres;
}else{
_throw("groupBy属性参数必须非空且为字符串");
}
}
function _getGroupAttrArr(arr,attr){
var res=[];
arr.forEach(function(item){
res.push(item[attr]);
});
return res;
}
function _geneGroupFuns(attr){
if(attr.timeOf(" ")>2){
_throw("参数错误:select 参数空格不能多于2个");
}else{
var res={};
if(_hasStr(attr,"(")&&_hasStr(attr,")")){
var arr=attr.split(")");
if(arr[1]!=""){
res.name=arr[1].substring(1);
}
attr=arr[0];
arr=attr.split("(");
res.attr=arr[1].toLowerCase();
if(_hasStr(arr[1]," ")){
arr[1]=arr[1].split(" ")[1];
}
if(!res.hasOwnProperty("name")){
res.name=arr[1];
}
res.fun=arr[0].toLowerCase();
}else{
if(_hasStr(attr," ")){
res.name=attr.split(" ")[1];
res.attr=attr.split(" ")[0];
}else{
res.attr=res.name=attr;
}
}
return res;
}
}
function _selectCount(get,attr,data){
if(attr.length>1){
_throw("使用count函数时select最多只能选择一列");
}
var obj=_geneGroupFuns(attr[0]);
var sum=0;
var result;
if(get.cond()===true){
result=[];
for(var i=0;i<data.length;i++){
if(_jqlCheckWhere(i,get)){
result.push(data[i]);
}
}
}else{
result=data;
}
if(_hasStr(obj.attr,FUN.distinct)){
var at=obj.attr.split(" ")[1];
var vs=[];
result.forEach(function(item){
if(!_hasStr(vs,item[at])){
vs.push(item[at]);
sum++;
}
});
}else{
if(obj.attr!=TYPE.all&&obj.attr!=""&&!result[0].hasOwnProperty(obj.attr)){
_throw("select:"+obj.attr+"属性不存在");
}
sum=result.length;
}
if(obj.name==TYPE.all||obj.name==""||obj.name==obj.attr){
obj.name=FUN.count;
}
var r={};
r[obj.name]=sum;
return r;
}
function _jqlRun(get,set){
var data=get.data();
var attr=get.attr();
var value=get.value();
var cond=get.cond();
switch(get.type()){
case TYPE.select:{
var result=[];
var dist=false;
var distArr=[];
var sum=0;
if(get.groupAttr()==""){//没使用groupBy
for(var i=0;i<data.length;i++){
if(_jqlCheckWhere(i,get)){
var r={};
if(attr==TYPE.all){
r=_clone(data[i]);
result.push(r);
}else{
if(_hasStr(attr[0],FUN.count)){//count 函数
result=_selectCount(get,attr,data);
break;
}else{
attr.forEach(function(a,j){
var name=a;//别名
if(_hasStr(a,FUN.count)){
_throw("使用count函数时select最多只能选择一列");
}
if(_hasStr(a," ")){//别名
var arr=a.split(" ");
if(arr.length>3){
_throw("select参数格式错误");
}else if(arr.length==3){
if(arr[0]!=FUN.distinct||j!=0){
_throw("distinct必须放在第一个参数前");
}
dist=true;
name=arr[2];
a=arr[1];
}else{
if(arr[0]==FUN.distinct){
if(j!=0){
_throw("distinct必须放在第一个参数前");
}
dist=true;
name=a=arr[1];
}else{
name=arr[1];
a=arr[0];
}
}
}
if(a in data[i]){
if(name in r){
_throw("select:["+name+"]列名不能重复");
}
r[name]=data[i][a];
}else{
if(_hasStr(a,"(")){
_throw("select:"+a.split("(")[0]+"函数要与groupBy配合使用");
}else{
_throw("select参数错误,对象不包含"+a+"属性");
}
}
});
if(dist){
var str=JSON.stringify(r);
if(!_hasStr(distArr,str)){
distArr.push(str);
result.push(r);
}
}else{
result.push(r);
}
}
}
}
}
_checkRunOrderBy(get,result);//对select结果order
}else{//使用groupBy
var funs=[];
attr.forEach(function(a){
if(_hasStr(a,FUN.distinct)){
_throw("groupBy与distinct不能共用");
}
funs.push(_geneGroupFuns(a));
});
if(funs.length>0){
set.groupFuns(funs);
}
result=_checkRunOrderBy(get,_clone(data));
result=_checkRunGroupBy(get,result);
}
_jqlReset(set);
return _jqlCheckReturn(result,get);
};break;
case TYPE.update:{
for(var i=0;i<data.length;i++){
if(_jqlCheckWhere(i,get)){
attr.forEach(function(item,j){
if(data[i].hasOwnProperty(item)){
data[i][item]=value[j];
}else{
_throw("属性不存在,若要添加新属性,请使用add方法");
}
});
}
}
_jqlReset(set);
return _jqlCheckReturn(data,get);
};break;
case TYPE.add:{
for(var i=0;i<data.length;i++){
if(_jqlCheckWhere(i,get)){
attr.forEach(function(item,j){
if(!data[i].hasOwnProperty(item)){
data[i][item]=value[j]
}else{
_throw("属性已存在,若要更新属性,请使用update方法");
}
});
}
}
_jqlReset(set);
return _jqlCheckReturn(data,get);
};break;
case TYPE.remove:{
for(var i=0;i<data.length;i++){
if(_jqlCheckWhere(i,get)){
if(attr==TYPE.all){
data[i]={};
}else{
for(var j=0;j<attr.length;j++){
delete data[i][attr[j]];
}
}
}
}
_jqlReset(set);
return _jqlCheckReturn(data,get);
};break;
case TYPE.insert:{
var obj={};
if(attr.constructor==Object){
obj=attr;
}else{
for(var i=0;i<attr.length;i++){
obj[attr[i]]=value[i];
}
}
if(get.index()>=0){
if(get.index()>=data.length){
set.index(data.length-1);
}
data.insert(obj,get.index());
}else{
data.push(obj);
}
_jqlReset(set);
return _clone(data);
};break;
case TYPE.delete:{
if(get.index()>=0){
if(_jqlCheckWhere(get.index(),get)){
data.removeByIndex(get.index());
}
}else{
var realI=0;
for(var i=0;i<data.length;i++){
if(_jqlCheckWhere(i,get,realI)){
data.removeByIndex(i);
i--;
}
realI++;
}
}
_jqlReset(set);
return _clone(data);
};break;
default:{
var res;
if(get.cond()===true){
res=[];
for(var i=0;i<data.length;i++){
if(_jqlCheckWhere(i,get)){
res.push(_clone(data[i]));
}
}
}else{
res=_clone(data);
}
if(get.orderAttr()!=""){//没有sele的order
res = _checkRunOrderBy(get,res);
}
if(get.groupAttr()!=""){//没有sele的group
res = _checkRunGroupBy(get,res);
}
_jqlReset(set);
return res;
};break;
}
}
function _jqlInitData(data,set){
if(data!=null){
if(data.constructor!=Object&&data.constructor!=Array){
set.canQuery(false);
}
}
}
function _jqlCheckRun(){
if(_checkArg.apply(null,arguments)&&this.run!=undefined){
return this.run();
}
return this;
}
function _checkArg(){
if(arguments.length==1){
return (arguments[0]===true);
}else{
for(var i=0;i<arguments.length;i++){
if(arguments[i]===true){
return true;
}
}
return false;
}
}
function _jqlReset(set){
set.attr([]);
set.value([]);
set.cond(false);
set.condAttr([]);
set.condValue([]);
set.index(-1);
set.sort("");
set.type("");
set.order("");
set.orderAttr("");
set.orderType("number");
set.groupAttr("");
set.groupFuns([]);
}
function _jqlCheckData(data){
if(this.data==undefined){
this.canQuery=false;
return true;
}else if(this.data.constructor==Object||this.data.constructor==Array){
if(data.constructor==String){
this.canQuery=true;
return false;
}else if(data.constructor==Object||data.constructor==Array){
this.canQuery=true;
return true;
}else{
this.canQuery=false;
_throw("参数错误");
}
}else{
if(data.constructor==Object||data.constructor==Array){
this.canQuery=true;
}else{
this.canQuery=false;
}
return true;
}
};
Jql=function(data){
return new JQL(data);
}
JQL=function(data){
var _canQuery=true;
var _data;
var _single=false;
if(data.constructor==Object){
_data=[data];
_single=true;
}else{
_data=data;
}
var _attr=[];
var _value=[];
var _cond=false;
var _cond_attr=[];
var _cond_value=[];
var _index=-1;
var _sort="";
var _type="";
var _order="";
var _order_attr="";
var _order_type="number";
var _group_attr="";
var _group_funs=[];
var set={
canQuery:function(val){
_canQuery=val;
},data:function(val){
_data = val;
},attr:function(val){
_attr =val;
},value:function(val){
_value =val;
},cond:function(val){
_cond =val;
},condAttr:function(val){
_cond_attr =val;
},condValue:function(val){
_cond_value =val;
},index:function(val){
_index =val;
},sort:function(val){
_sort =val;
},type:function(val){
_type =val;
},order:function(val){
_order =val;
},orderAttr:function(val){
_order_attr =val;
},orderType:function(val){
_order_type =val;
},groupAttr:function(val){
_group_attr =val;
},groupFuns:function(val){
_group_funs =val;
}
};
var get={
canQuery:function(){
return _canQuery;
},data:function(){
return _data;
},attr:function(){
return _attr;
},value:function(){
return _value;
},cond:function(){
return _cond;
},condAttr:function(){
return _cond_attr;
},condValue:function(){
return _cond_value;
},index:function(){
return _index;
},sort:function(){
return _sort;
},type:function(){
return _type;
},single:function(){
return _single;
},order:function(){
return _order;
},orderAttr:function(){
return _order_attr;
},orderType:function(){
return _order_type;
},groupAttr:function(){
return _group_attr;
},groupFuns:function(){
return _group_funs;
}
}
_jqlInitData(data,set);
if(data.constructor==Object){
this.add=function(attr,value){
_jqlAdd.call(this,get,set,attr,value);
return _jqlRun.call(this,get,set);
};
this.remove=function(attr){
_jqlRemove.call(this,get,set,attr,true);
return _jqlRun.call(this,get,set);
};
this.select=function(attr){
_jqlSelect.call(this,get,set,attr,true);
return _jqlRun.call(this,get,set);
};
this.update=function(attr,value){
_jqlUpdate.call(this,get,set,attr,value,true);
return _jqlRun.call(this,get,set);
};
}else if(data.constructor==Array){
this.add=function(attr,value,run){
return _jqlAdd.call(this,get,set,attr,value,run);
};
this.remove=function(attr,run){
return _jqlRemove.call(this,get,set,attr,run);
};
this.insert=function(attr,value,index,run){
return _jqlInsert.call(this,get,set,attr,value,index,run);
};
this.delete=function(index,run){
return _jqlDelete.call(this,get,set,index,run);
};
this.select=function(attr,run){
return _jqlSelect.call(this,get,set,attr,run);
};
this.update=function(attr,value,run){
return _jqlUpdate.call(this,get,set,attr,value,run);
};
this.run=function(){
return _jqlRun.call(this,get,set);
};
this.where=function(attr,value,run){
return _jqlWhere.call(this,get,set,attr,value,run);
};
this.orderBy=function(attr,order,type,run){
return _jqlOrderBy.call(this,get,set,attr,order,type,run);
};
this.groupBy=function(attr,run){
return _jqlGroupBy.call(this,get,set,attr,run);
};
}
this.set=function(data){
var datac=_clone(data);
if(datac.constructor==Object){
datac=[datac];
}
if(_data.constructor!=datac.constructor){
_throw("数据类型不同,无法执行set");
}else{
_data=datac;
return data;
}
};
this.get=function(){
if(_single){
return _clone(_data[0]);
}
return _clone(_data);
};
this.data=function(){
if(_single){
return _data[0];
}
return _data;
};
this.clear=function(){
_data=null;
return null;
}
};
var Jql;
var JQL;
if (typeof module !== 'undefined') {
module.exports = Jql;
} else {
if(typeof window.Jql!=='undefined'){
window.Jql = Jql
}else{
window.$Jql = Jql
}
}
})();