angular处理后端返回的嵌套型Json数据以生成多种语言的菜单
根据用户权限的不同,网页应用的菜单不同。这个菜单的控制可以由前端生成,也可以由后端生成,从安全方面考虑,当然是后端生成更好一些。后端在数据库里存储相关的菜单数据,在前端用户登录请求时,后端根据用户权限读取数据库数据,生成嵌套型的Json格式数据,返回给前端。为了改进用户体验,一般将英文菜单、中文菜单或其他文的菜单一次生成,返回给前端,存储在localstorage或sessionstorage里。前端在需要时提取使用。
然而,当你在localstorage里或sessionstrorage里存储后端返回的嵌套型Json时,会发现存储的其实是一个Object,根本无法按照Json的样子去读取它。原因是localstorage和sessionstorage只能存储字符串型的json数据,因此需要先把json数据转化成字符串,使用函数JSON.stringify(value)即可将其转成字符串类型。如以下代码:
this.http.put("/api/login",data,httpOptions).subscribe(response => { this.transformMenu(response["englishMenu"],this.menus_en); //转换成目标样式(英文菜单) sessionStorage.setItem("englishMenu",JSON.stringify(this.menus_en)); //转成字符串格式后存储到session中(英文菜单) this.transformMenu(response["chineseMenu"],this.menus_cn); //转换成目标样式(中文) sessionStorage.setItem("chineseMenu",JSON.stringify(this.menus_cn)); //转成字符串格式后存储到session中(中文) });
上述代码中的transformMenu是一个自定义方法,目的是把接收到的后端json数据略为加工,使之符合格式要求,主要代码如下(当然根据自己的网页应用实际情况,也可以不做处理,只要后端返回的数据完全满足前端的要求)。
//自定义一个json数据类型
interface secmenus { ID: string, PID: string, MENUID: string, MENUNAME: string, ENABLE: string, WXMENU: string, MENUTYPE: string, HASCHILD: string, MENUICON: string, PARENT: string, SORT: number, ROUTER: string, P_CHILDMENUS: secmenus[] } menus_cn: secmenus[]=[]; //空数组,用于存放中文菜单 menus_en: secmenus[]=[]; //空数组,用于存放英文菜单
//转换后端的Json,得到新的json数组,此处需要注意,menuJson不能用存储在sessionstorage里的数据 transformMenu(menuJson:any,menus:secmenus[]): void{ for(let i=0;i<menuJson.length;i++){ var menu: secmenus={ID:"", PID: "",MENUID: "",MENUNAME: "",ENABLE: "", WXMENU: "",MENUTYPE: "", HASCHILD: "N", MENUICON: "", PARENT: "", SORT: 0, ROUTER: "", P_CHILDMENUS: []}; menus.push(menu); if(menuJson[i].children.length>0){ this.transformMenu(menuJson[i].children,menu.P_CHILDMENUS) //如果有下一层json,则递归找出每一层数据 menus[i].HASCHILD="Y"; }
//以下将后端的json里的各个值传给前端的json menus[i].ID=menuJson[i].iD; menus[i].PID=menuJson[i].pID; menus[i].MENUNAME=menuJson[i].name; menus[i].MENUID=menuJson[i].mENUID; menus[i].ENABLE=menuJson[i].eNABLE; menus[i].WXMENU=menuJson[i].wXMENU; menus[i].MENUTYPE=menuJson[i].mENUTYPE; menus[i].MENUICON=menuJson[i].mENUICON; menus[i].PARENT=menuJson[i].pARENT; menus[i].SORT=menuJson[i].sORT; menus[i].ROUTER=menuJson[i].rOUTER; } }
这时,我们就在sessionstorage里存下了englishMenu和chineseMenu两个菜单,其他类和方法就可以直接调用这两个菜单了。但是,问题又来了,存储在sessionstorage里的其实是字符串,不是json数据,无法用menus.ROUTER这样的方式来得到相应的值。这时需要将字符串转换成json,可使用方法JSON.parse(value)。然而,问题并不是我们想象的那样用这个简单的方法就可以实现,因为这里是一个嵌套的json字符串,使用一次JSON.parse(value)只能得到最外一层json数据,嵌套其中的json数据却仍然是字符串,无法用menus.ROUTER这样的方式得到相应的值。这时就需要再次用递归的方法来转换,代码如下。
/** * 获取菜单Json数组 */ getMenus(language:string) { var secmenu:any={P_MENUS:[]}; if(language=="zh"){ secmenu.P_MENUS[0]=this.StringToJson(sessionStorage.getItem("chineseMenu")); //用户调用中文菜单时,将存储在sessionStorage里的菜单取出并转换 return secmenu.P_MENUS[0]; }
else if(language=="en"){ secmenu.P_MENUS[0]=this.StringToJson(sessionStorage.getItem("englishMenu"));//用户调用中文菜单时,将存储在sessionStorage里的菜单取出并转换
return secmenu.P_MENUS[0];
}else{
return menus;
}
}
/** * 将字符串转换成JSON
* @param str
* @returns
*/
StringToJson(str:any): any{
var js=JSON.parse(str);
if(js.HASCHILD=="Y"){
this.StringToJson(js.P_CHILDMENUS); //对于有下一层的json,递归调用
}
return JSON.parse(str);
}
浙公网安备 33010602011771号