javascript - 關於json中取得多個key-value對中多層嵌套key的name
ringa_lee
ringa_lee 2017-06-12 09:22:48
0
6
875
{
  "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實作都可以

ringa_lee
ringa_lee

ringa_lee

全部回覆(6)
黄舟

雷雷

漂亮男人
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 替换为 toPlace
var 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

世界只因有你
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,這個沒事兒

Ty80

如果是要用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]
世界只因有你

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)
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板