json文件的查询

yaotomo 2018-08-14 11:04:04
数据保存在一个json格式的文件中,网页打开时加载这个json文件,读取其中的数据,生成地名树(省市区)。
每个地名节点上有不同的管理员(一个管理员也可以管理多个地名节点)
要求每个管理员登录后,显示出的树只包含自己所管理的地区。
比如一个用户为湖北、郑州市两个节点的管理员
那么他登陆后,应该显示湖北省下的所有市、区。还有河南省郑州市(不显示除郑州外市的节点)以及郑州下的区。
所有管理员登录都读取这个json文件。
如何按权限读取出每个管理员对应的地名节点树?(每个用户登录时可以从数据库获取自己管理的地区节点,这里的节点不包括其下的子节点,如管理郑州市,可以得到郑州市的nodeid,而显示到前台不仅要显示父节点河南省,也要显示其下的各个区)
json格式类似下面的(截取一部分)

[{
"text": "中华人民共和国",
"spid": "2013010535",
"nodes": [{
"text": "东北",
"spid": "2013010535",
"nodes": [{
"text": "辽宁省",
"spid": "2013035210",
"nodes": [{
"text": "沈阳市",
"spid": "2013035211",
"nodes": [{
"text": "沈阳市和平区",
"spid": "2013038441"
}, {
"text": "沈河区",
"spid": "2013038441"
}, {
"text": "大东区",
"spid": "2013038441"
}, {
"text": "皇姑区",
"spid": "2013038441"
}, {
"text": "沈阳市铁西区",
"spid": "2013038441"
}, {
"text": "苏家屯区",
"spid": "2013038441"
}, {
"text": "东陵区",
"spid": "2013038441"
}, {
"text": "沈北新区",
"spid": "2013038441"
}, {
"text": "于洪区",
"spid": "2013038441"
}, {
"text": "辽中县",
"spid": "2013038441"
}, {
"text": "康平县",
"spid": "2013038441"
}, {
"text": "法库县",
"spid": "2013038441"
}, {
"text": "新民市",
"spid": "2013038441"
}]
}, {
"text": "大连市",
"spid": "2013035211",
"nodes": [{
"text": "中山区",
"spid": "2013038441"
}, {
"text": "西岗区",
"spid": "2013038441"
}, {
"text": "沙河口区",
"spid": "2013038441"
}, {
"text": "甘井子区",
"spid": "2013038441"
}, {
"text": "旅顺口区",
"spid": "2013038441"
}, {
"text": "金州区",
"spid": "2013038441"
}, {
"text": "长海县",
"spid": "2013038441"
}, {
"text": "瓦房店市",
"spid": "2013038441"
}, {
"text": "普兰店市",
"spid": "2013038441"
}, {
"text": "庄河市",
"spid": "2013038441"
}]
}]
}]
}]
}]
...全文
460 21 打赏 收藏 转发到动态 举报
写回复
用AI写文章
21 条回复
切换为时间正序
请发表友善的回复…
发表回复
讨厌走开啦 2018-08-21
  • 打赏
  • 举报
回复
function merge (map1, map2) {
let result = [], tmp1 = JSON.parse(JSON.stringify(map1)), tmp2 = JSON.parse(JSON.stringify(map2));
tmp1.forEach(function (item1) {
let flag = false;
tmp2.forEach(function (item2) {
if (item1.nodeid === item2.nodeid) {
flag = true;
result.push({
name: item1.name,
nodeid: item1.nodeid,
nodes: merge(item1.nodes, item2.nodes)
});
}
});
if (!flag) result.push(item1);
});
tmp2.forEach(function (item2) {
let flag = false;
tmp1.forEach(function (item1) {
if (item1.nodeid === item2.nodeid) flag = true;
});
if (!flag) result.push(item2);
});
return result;
}


仅供参考
yaotomo 2018-08-21
  • 打赏
  • 举报
回复
引用 20 楼 lqlqlq007 的回复:
function merge (map1, map2) {
let result = [], tmp1 = JSON.parse(JSON.stringify(map1)), tmp2 = JSON.parse(JSON.stringify(map2));
tmp1.forEach(function (item1) {
let flag = false;
tmp2.forEach(function (item2) {
if (item1.nodeid === item2.nodeid) {
flag = true;
result.push({
name: item1.name,
nodeid: item1.nodeid,
nodes: merge(item1.nodes, item2.nodes)
});
}
});
if (!flag) result.push(item1);
});
tmp2.forEach(function (item2) {
let flag = false;
tmp1.forEach(function (item1) {
if (item1.nodeid === item2.nodeid) flag = true;
});
if (!flag) result.push(item2);
});
return result;
}


仅供参考


自己稍微修改了一下可以用了,谢谢!
yaotomo 2018-08-20
  • 打赏
  • 举报
回复
我在网上查了有$.extend()可以合并,但都是简单对象的合并
yaotomo 2018-08-20
  • 打赏
  • 举报
回复
引用 17 楼 lqlqlq007 的回复:
因为subMap.nodes = subRe这一句会改变原始map对象,另外你尝试用var json2 = json来完成拷贝,可惜这只对基本数据类型有效(就是布尔,整数这些),对复杂对象是无效的,JSON可以用我上面的代码复制,其他对象可以百度一下对象的深拷贝。


谢谢老师,已经可以了
不过还有最后一个没有解决的问题
如果我通过传入不同的参数得到了多个对象
怎么做能合并为一个对象呢?
比如一个对象显示的是中国->河南->郑州->郑州下的区县
另一个对象显示的是中国->湖北->湖北下所有的市->湖北下所有市的所有区县
把他们合并都合并到一个json对象里
要怎么做呢
讨厌走开啦 2018-08-20
  • 打赏
  • 举报
回复
引用 13 楼 yaotomo 的回复:
[quote=引用 11 楼 lqlqlq007 的回复:]
我的方法仅供参考哈,有几种情况都没考虑:

1.map数据不包含nodeid的情况;
2.map数据中包含重复nodeid的情况。

另外我看了下的贴图,为什么的map数据里,有些地址信息是spid,有些是nodeid,如果要支持的nodeid也可以是spid的话,还要额外做特殊处理哦。


你好老师
我用下面的代码实现了功能

function up(nodeid, map) {
var currentMap = null;
map.forEach(function (subMap) {
if (subMap.nodeid == nodeid) currentMap = subMap;
});
if (currentMap !== null) {
return currentMap;
}
else {
var result = null;
map.forEach(function (subMap) {
if (subMap.hasOwnProperty("nodes")) {
var subRe = up(nodeid, subMap.nodes);
if (subRe != null) {
subMap.nodes = subRe;
result = subMap;
}
}
});
return result;
}
}

但是奇怪的是,我第一次调用是可以的,第二次调用就会报错

var res1 = up('133619', json);
var res2 = up('133992', json);

下面是错误

json.aspx:73 Uncaught TypeError: map.forEach is not a function
at up (json.aspx:73)
at json.aspx:83
at Array.forEach (<anonymous>)
at up (json.aspx:81)
at Object.success (json.aspx:60)
at fire (jquery.js:2913)
at Object.fireWith [as resolveWith] (jquery.js:3025)
at done (jquery.js:7400)
at XMLHttpRequest.<anonymous> (jquery.js:7822)

原来第二次调用,map的值为null所以报错
就算我再建一个方法up1(),写同样的代码在里面
运行也会报错。但是单独调用一次都是正常的。
这是怎么回事?[/quote]

把第二次传入的json打印出来看看
讨厌走开啦 2018-08-20
  • 打赏
  • 举报
回复
引用 16 楼 yaotomo 的回复:

var json = $.parseJSON(response);
var json2 = json;
console.log(json);
var res1 = up('133619', json);
console.log(json2);

json和json2打印的结果,都是up()方法的返回值
虽然将json赋值给json2,但是引用没有变化,所以一个修改了,另一个也跟着变化?


引用 16 楼 yaotomo 的回复:

var json = $.parseJSON(response);
var json2 = json;
console.log(json);
var res1 = up('133619', json);
console.log(json2);

json和json2打印的结果,都是up()方法的返回值
虽然将json赋值给json2,但是引用没有变化,所以一个修改了,另一个也跟着变化?


用下面的代码,把传入的map复制一份:
function up(nodeid, map) {
let currentMap = null, tmp = JSON.parse(JSON.stringify(map));
tmp.forEach(function (subMap) {
if (subMap.nodeid === nodeid) currentMap = subMap;
});
if (currentMap !== null) {
return [currentMap];
} else {
let result = null;
tmp.forEach(function (subMap) {
if (subMap.hasOwnProperty("nodes")) {
let subRe = up(nodeid, subMap.nodes);
if (subRe !== null) subMap.nodes = [subRe]; result = subMap;
}
});
return [result];
}
}


因为subMap.nodes = subRe这一句会改变原始map对象,另外你尝试用var json2 = json来完成拷贝,可惜这只对基本数据类型有效(就是布尔,整数这些),对复杂对象是无效的,JSON可以用我上面的代码复制,其他对象可以百度一下对象的深拷贝。
yaotomo 2018-08-20
  • 打赏
  • 举报
回复

var json = $.parseJSON(response);
var json2 = json;
console.log(json);
var res1 = up('133619', json);
console.log(json2);

json和json2打印的结果,都是up()方法的返回值
虽然将json赋值给json2,但是引用没有变化,所以一个修改了,另一个也跟着变化?
yaotomo 2018-08-20
  • 打赏
  • 举报
回复
引用 14 楼 lqlqlq007 的回复:
把第二次传入的json打印出来看看



var json = $.parseJSON(response);
console.log(json); //查询前
var res1 = up('133619', json);
console.log(json); //查询后

第一个打印的json是全中国的行政区域,经过一次查询后,改变了json的结构,成了第一次的查询结果
连查询前的json变量也跟着改了

我试了一下,下面的代码

var json = $.parseJSON(response);
var json2 = json;
console.log(json);
var res1 = up('133619', json);
console.log(json2);

json和json2打印的结果相同
是怎么回事

我想每次传入一个nodeid,查询后不影响原来的json结构,只返回查询的结果(新生成的json对象)
yaotomo 2018-08-19
  • 打赏
  • 举报
回复
引用 11 楼 lqlqlq007 的回复:
我的方法仅供参考哈,有几种情况都没考虑:

1.map数据不包含nodeid的情况;
2.map数据中包含重复nodeid的情况。

另外我看了下的贴图,为什么的map数据里,有些地址信息是spid,有些是nodeid,如果要支持的nodeid也可以是spid的话,还要额外做特殊处理哦。


你好老师
我用下面的代码实现了功能

function up(nodeid, map) {
var currentMap = null;
map.forEach(function (subMap) {
if (subMap.nodeid == nodeid) currentMap = subMap;
});
if (currentMap !== null) {
return currentMap;
}
else {
var result = null;
map.forEach(function (subMap) {
if (subMap.hasOwnProperty("nodes")) {
var subRe = up(nodeid, subMap.nodes);
if (subRe != null) {
subMap.nodes = subRe;
result = subMap;
}
}
});
return result;
}
}

但是奇怪的是,我第一次调用是可以的,第二次调用就会报错

var res1 = up('133619', json);
var res2 = up('133992', json);

下面是错误

json.aspx:73 Uncaught TypeError: map.forEach is not a function
at up (json.aspx:73)
at json.aspx:83
at Array.forEach (<anonymous>)
at up (json.aspx:81)
at Object.success (json.aspx:60)
at fire (jquery.js:2913)
at Object.fireWith [as resolveWith] (jquery.js:3025)
at done (jquery.js:7400)
at XMLHttpRequest.<anonymous> (jquery.js:7822)

原来第二次调用,map的值为null所以报错
就算我再建一个方法up1(),写同样的代码在里面
运行也会报错。但是单独调用一次都是正常的。
这是怎么回事?
yaotomo 2018-08-18
  • 打赏
  • 举报
回复
引用 11 楼 lqlqlq007 的回复:
我的方法仅供参考哈,有几种情况都没考虑:

1.map数据不包含nodeid的情况;
2.map数据中包含重复nodeid的情况。

另外我看了下的贴图,为什么的map数据里,有些地址信息是spid,有些是nodeid,如果要支持的nodeid也可以是spid的话,还要额外做特殊处理哦。


map数据一定会包含nodeid。因为JSON数据是固定的。
不包含重复nodeid,因为从数据库表导出JSON时,nodeid是主键,每个地区的nodeid是不同的
一楼贴的JSON代码,我还没把nodeid给加上去。后来又重新生成了JSON数据。spid也是唯一的,但是现在需要查询的是nodeid。
讨厌走开啦 2018-08-17
  • 打赏
  • 举报
回复
我的方法仅供参考哈,有几种情况都没考虑:

1.map数据不包含nodeid的情况;
2.map数据中包含重复nodeid的情况。

另外我看了下的贴图,为什么的map数据里,有些地址信息是spid,有些是nodeid,如果要支持的nodeid也可以是spid的话,还要额外做特殊处理哦。
yaotomo 2018-08-16
  • 打赏
  • 举报
回复
引用 9 楼 lqlqlq007 的回复:
function up(nodeid, map) {
let currentMap = null;
map.forEach(function (subMap) {
if (subMap.nodeid === nodeid) currentMap = subMap;
});
if (currentMap !== null) {
return [currentMap];
} else {
let result = null;
map.forEach(function (subMap) {
if (subMap.hasOwnProperty("nodes")) {
let subRe = up(nodeid, subMap.nodes);
if (subRe !== null) subMap.nodes = [subRe]; result = subMap;
}
});
return [result];
}
}


向上遍历,仅供参考。


你好老师,昨天晚上我运行了你的代码,也看了好久,自己理解了一下,最后也不是特别明白
意思就是判断传入的nodeid是否包含在节点集合中
先检查nodeid在不在当前传入节点的子节点中,如果在就返回,不在就递归查询

但是结果总是错误的,比如我搜索鞍山市,它的nodeid是133695
if (currentMap !== null) {
return [currentMap];
}
当运行到这里的时候,返回了鞍山市和鞍山市下的所有县区,这里没有问题


但是最终递归生成的结果却是这样的,似乎向上遍历的时候出了问题?


这个西藏林芝地区是JSON字符串最后一个节点
也就是代表遍历到最后也没有获取到鞍山市的节点树??

还有一个问题就是,如果我有两个nodeid
比如鞍山市和武汉市,怎么将他们两个得到的节点树合并为一个树?请老师给一下思路
讨厌走开啦 2018-08-15
  • 打赏
  • 举报
回复
function up(nodeid, map) {
let currentMap = null;
map.forEach(function (subMap) {
if (subMap.nodeid === nodeid) currentMap = subMap;
});
if (currentMap !== null) {
return [currentMap];
} else {
let result = null;
map.forEach(function (subMap) {
if (subMap.hasOwnProperty("nodes")) {
let subRe = up(nodeid, subMap.nodes);
if (subRe !== null) subMap.nodes = [subRe]; result = subMap;
}
});
return [result];
}
}


向上遍历,仅供参考。
yaotomo 2018-08-15
  • 打赏
  • 举报
回复
引用 7 楼 lqlqlq007 的回复:
分成向上递归和向下递归,向上递归获取区域范围大于当前节点的区县信息,向下递归获取区域范围小于等于当前节点的区县信息。


我也知道原理,就是不知道怎么写

json里应该多加一个parentid的属性
讨厌走开啦 2018-08-15
  • 打赏
  • 举报
回复
分成向上递归和向下递归,向上递归获取区域范围大于当前节点的区县信息,向下递归获取区域范围小于等于当前节点的区县信息。
yaotomo 2018-08-15
  • 打赏
  • 举报
回复
引用 4 楼 foren_whb 的回复:



for (var i = 0; i < regions.length; i++) {
/*
遍历各个地区,打印结果示例
console.log(regions[i]);
{text: "东北", nodeid: "137697", spid: "2013358041", nodes: Array(3)}
*/
var provinces = regions[i].nodes;
for (var j = 0; j < provinces.length; j++) {
/*
遍历各个省,打印结果示例
console.log(provinces[j]);
{text: "辽宁省", nodeid: "133596", spid: "2013035210", nodes: Array(14)}
*/
var cities = provinces[j].nodes;
for (var k = 0; k < cities.length; k++) {
/*
遍历各个市,打印结果示例
console.log(cities[k]);
{text: "沈阳市", nodeid: "133693", spid: "2013035211", nodes: Array(13)}
*/
var couties = cities[k].nodes;
for (var m = 0; m < couties.length; m++) {
/*
打印各个县、区,打印结果示例
console.log(couties[m]);
{text: "沈阳市和平区", nodeid: "134494", spid: "2013038441"}
*/
}
}
}


以上是我嵌套循环的代码
假设现在用户是沈阳市的管理员,我要求得到东北地区、辽宁省、沈阳市、沈阳市下所有区县。这样一棵树的JSON,应该怎么操作?
yaotomo 2018-08-14
  • 打赏
  • 举报
回复
引用 1 楼 foren_whb 的回复:
遍历json并判断管理员是否是当前登陆的管理员


我想知道如何通过某个nodeid得到它的父节点和所有子节点
用js怎么操作
丰云 2018-08-14
  • 打赏
  • 举报
回复
遍历json并判断管理员是否是当前登陆的管理员
丰云 2018-08-14
  • 打赏
  • 举报
回复
像这样标准的结构,甚至不需要递归,因为层数有限,直接for循环嵌套就好了
var json = [...];
for(var i = 0; i < json.length(); i++){
var node = josn[i];
alert(node.text);
for(var j = 0; j < node.nodes.length(); j++){
var child= node.nodes[j];
alert(child.text);
for(var k = 0; k < child.nodes.length();k++){
var last= child.nodes[k];
alert(last.text);
}
}
}
丰云 2018-08-14
  • 打赏
  • 举报
回复
就算没学过二叉树原理,普通的递归遍历也该知道吧。。。。。

这还要问吗?

87,990

社区成员

发帖
与我相关
我的任务
社区描述
Web 开发 JavaScript
社区管理员
  • JavaScript
  • 无·法
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧