javascript - 关于json中获取多个key-value对中多层嵌套key的name
问题描述
{ 'RuntimeSources': { 'flask-webapp': { 'eb-flask1.3': {'s3url': '' } } }, 'DeploymentId': 4, 'Serial': 4}
有这样一个json文件, 我现在我需要提取出flask-webapp这个key的name,即flask-webapp这个字符串本身,我应该如何使用呢?使用Object.keys()的话我得到的是RuntimeSource,DeploymentId和Serial这三个key。感觉自己描述的有些复杂,问题提炼一下就是:如何提取这个json文件的第一个key-value中的下一层key-value中的key(好像说的更复杂了。。希望能看懂吧)用python或者javascript实现都可以
问题解答
回答1:function getFirstKeyInLevel(json, level) { var levelNow = 0; var key; var obj = json; do {key = Object.keys(obj)[0];levelNow++;obj = obj[key]; } while (key && levelNow < level); return key;}var json = { ’RuntimeSources’: {’flask-webapp’: { ’eb-flask1.3’: {’s3url’: ’’ }} }, ’DeploymentId’: 4, ’Serial’: 4};console.log(getFirstKeyInLevel(json, 1)); // RuntimeSourcesconsole.log(getFirstKeyInLevel(json, 2)); // flask-webappconsole.log(getFirstKeyInLevel(json, 3)); // eb-flask1.3console.log(getFirstKeyInLevel(json, 4)); // s3urlconsole.log(getFirstKeyInLevel(json, 5)); // undefined回答2:
var o = { 'RuntimeSources': { 'flask-webapp': { 'eb-flask1.3': {'s3url': '' } } }, 'DeploymentId': 4, 'Serial': 4}
这是需要处理的数据,题主的问题应该可以看成下面问题的一个真子集 (问题是只要取得 'flask-webapp')
从对象里抽离出该对象的全部键名,并构成一个数组
这个过程 暂且称之为 铺平 flat, 我这里也实现了这个函数 用于取得这个解。
flat(o); // => // ['RuntimeSources', 'flask-webapp', 'eb-flask1.3', 's3url', 'DeploymentId', 'Serial']利用 Object.keys 解决问题
Object.keys 能获得可枚举的第一层对象属性键名
利用这样的特性编写递归函数:
var flat = o => { // 当层键名 if (typeof o !== ’object’) return []; var keys = Object.keys(o); return keys.reduce((acc, cur) => {return acc.concat( flat(o[cur]) ); }, keys); }ScreenShot
var log = (item, idx) => { console.group(`第 ${idx + 1} 个元素`) console.log(’值:’, item); console.groupEnd(); }flat(o).forEach(log);
特别地 你需要 flask-webapp 这个键名:
var res = flat(o).filter(e => e === ’flask-webapp’); console.log(res); // => // ['flask-webapp'] 利用 JSON.stringify 解决问题
JSON.stringify 可以把对象转化成 JSON字符串
比如 JSON.stringify(o) 可以得到结果'{'RuntimeSources':{'flask-webapp':{'eb-flask1.3':{'s3url':''}}},'DeploymentId':4,'Serial':4}'
继续观察可以发现:
在 JSON 中, : 前的是键名
把 JSON 的元素构成一个数组,再把 冒号 前的挑出来就可以了。
工具函数
// 把在 str 中的 willBeReplaced 替换为 toPlacevar replaceAll = (str, willBeReplaced, toPlace) => { return str.split(willBeReplaced).join(toPlace)}// 把在 str 的全部 willBeCut 替换成 ’’var cut = (str, willBeCut) => { return replaceAll(str, willBeCut, ’’); }
flat 的实现
var flat = o => { var str = JSON.stringify(o); return [’{’, ’}’, ’:’, ’,’].reduce((acc, e) => {return replaceAll(acc, e, ` ${e} `); }, str).split(’ ’).filter(e => e !== '').reduce((acc, cur, idx, its) => {if (cur === ’:’){ acc.push(its[idx - 1]); }return acc; }, []).map(e => cut(e, ’'’, ’’)); }
上面的意思是:
第一个 reduce 给 { } : , 的前后补了空格对应代码
// o 是待处理对象 let str = JSON.stringify(o); var A = [’{’, ’}’, ’:’, ’,’].reduce((acc, e) => { // 把 e 的两侧都补上一个空格 return replaceAll(acc, e, ` ${e} `); }, str)
结果是这样的:
原来的 str 从
'{'RuntimeSources':{'flask-webapp':{'eb-flask1.3':{'s3url':''}}},'DeploymentId':4,'Serial':4}'
经过处理后 变成
' { 'RuntimeSources' : { 'flask-webapp' : { 'eb-flask1.3' : { 's3url' : '' } } } , 'DeploymentId' : 4 , 'Serial' : 4 } '
得到一个中间结果 A
Next这里要处理 A
对应代码:
var B = [’{’, ’}’, ’:’, ’,’].reduce((acc, e) => { return replaceAll(acc, e, ` ${e} `); }, str).split(’ ’).filter(e => e !== '')
把 A 转成中间数组 B: (从字符串变成数组)
最后一个 reduce 得到结果观察 B 可以得到一个结论
在 JSON 中, : 前的是键名
据此写出 最后的reduce:把 冒号 前的元素收集起来 得到结果
ScreenShot回答3:var object= { 'RuntimeSources': { 'flask-webapp': { 'eb-flask1.3': {'s3url': '' } } }, 'DeploymentId': 4, 'Serial': 4} for(i in object){console.log(Object.keys(object[i]));// console.log(object[i]);//Object {flask-webapp: Object} 执行四次for(k in object[i]){ console.log(Object.keys(object[i][k])); // console.log(object[i][k]);//Object {eb-flask1.3: Object} for(s in object[i][k]){console.log(Object.keys(object[i][k][s]));//console.log(object[i][k][s])//Object {s3url: ''}for( f in object[i][k][s]){ console.log(Object.keys(object[i][k][f]))} }} }
执行到最后应该会抛出错误 Cannot convert undefined or null to object,这个没事儿
回答4:如果是要用python实现的话,dict是一种散列表结构,就是说数据输入后按特征已经被散列了,有自己的顺序如果你可以指定key的名字倒还可以获取,如果不能指定key的名字,那就做不到
data = { 'RuntimeSources': { 'flask-webapp': { 'eb-flask1.3': {'s3url': '' } } }, 'DeploymentId': 4, 'Serial': 4}print data[’RuntimeSources’][’flask-webapp’]print data[’RuntimeSources’].values()[0]回答5:
python 默认字典是无序的,但是可以用 OrderedDict 有序字典来实现。
def level_keys(order_dict, level): _level = 1 if level == _level:return order_dict.get(order_dict.keys()[0]).keys() else:return level_keys(order_dict.get(order_dict.keys()[0]), level=level - 1)def main(level=1): from collections import OrderedDict import json dict_str = '''{ 'RuntimeSources': { 'flask-webapp': { 'eb-flask1.3': {'s3url': '' } } }, 'DeploymentId': 4, 'Serial': 4}''' order_dict = json.loads(s=dict_str, object_pairs_hook=OrderedDict) print(level_keys(order_dict, level))if __name__ == ’__main__’: main(3)回答6:
var json = JSON.parse(’{ 'RuntimeSources': { 'flask-webapp': { 'eb-flask1.3': {'s3url': '' } } }, 'DeploymentId': 4, 'Serial': 4}’);for (t in json) { console.log(t); }var test = Object.keys(json);console.log(test[0]);
相关文章:
1. nignx - docker内nginx 80端口被占用2. docker gitlab 如何git clone?3. docker镜像push报错4. dockerfile - [docker build image失败- npm install]5. objective-c - iOS开发支付宝和微信支付完成为什么跳转到了之前开发的一个app?6. angular.js - 求一款angular插件7. font-family - 我引入CSS3自定义字体没有效果?8. PHP中的$this代表当前的类还是方法?9. macos - mac下docker如何设置代理10. docker images显示的镜像过多,狗眼被亮瞎了,怎么办?