首頁  >  問答  >  主體

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實作都可以

ringa_leeringa_lee2686 天前838

全部回覆(6)我來回復

  • 黄舟

    黄舟2017-06-12 09:24:48

    雷雷

    回覆
    0
  • 漂亮男人

    漂亮男人2017-06-12 09:24:48

    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

    回覆
    0
  • 世界只因有你

    世界只因有你2017-06-12 09:24:48

    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,這個沒事兒

    回覆
    0
  • PHP中文网

    PHP中文网2017-06-12 09:24:48

    如果是要用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]

    回覆
    0
  • 世界只因有你

    世界只因有你2017-06-12 09:24:48

    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)
    

    回覆
    0
  • 曾经蜡笔没有小新

    曾经蜡笔没有小新2017-06-12 09:24:48

    雷雷

    回覆
    0
  • 取消回覆