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);
}

 

posted @ 2021-12-07 20:32  wwwzgy  阅读(379)  评论(0)    收藏  举报