2017-11-14 14 views
0

私は以下のようなJSONファイルを解析するPythonスクリプトがあります。PythonのJSON移動子キー

[ 
    { 
    "_index": "bulletins", 
    "_type": "bulletin", 
    "_id": "OPENWRT-SA-000001", 
    "_score": null, 
    "_source": { 
     "lastseen": "2016-09-26T15:45:23", 
     "references": [ 
     "http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2015-3193", 
     ], 
     "affectedPackage": [ 
     { 
      "OS": "OpenWrt", 
      "OSVersion": "15.05", 
      "packageVersion": "9.9.8-P3-1", 
      "packageFilename": "UNKNOWN", 
      "arch": "all", 
      "packageName": "bind", 
      "operator": "lt" 
     } 
     ], 
     "edition": 1, 
     "description": "value in here, 
     "reporter": "OpenWrt Project", 
     "published": "2016-01-24T13:33:41", 
     "title": "bind: Security update (4 CVEs)", 
     "type": "openwrt", 
     "bulletinFamily": "unix", 
     "cvelist": [ 
     "CVE-2015-8704", 
     ], 
     "modified": "2016-01-24T13:33:41", 
     "id": "OPENWRT-SA-000001", 
     "href": "https://lists.openwrt.org/pipermail/openwrt-security-announce/2016-January/000001.html", 
     "cvss": { 
     "score": 7.1, 
     "vector": "AV:NETWORK/AC:MEDIUM/Au:NONE/C:NONE/I:NONE/A:COMPLETE/" 
     } 
    }, 
    "sort": [ 
     34872 
    ] 
    }, 

を私はポスト短いを維持するために一部の値を削除だけにしようとする中、一部を残しています構造を守ってください。

_sourceキーからすべてのサブキーを取り出し、_sourceと同じレベルまで移動し、_sourceキーを削除します。 JSONを解析する

私のコードは次のとおりです。あなたが見ることができる

import json 
import logging 
import logging.handlers 
import os 
import pymongo 
from pymongo import MongoClient 


def import_json(mongo_server,mongo_port, vuln_folder): 
    try: 
     logging.info('Connecting to MongoDB') 
     client = MongoClient(mongo_server, mongo_port) 
     db = client['vuln_sets'] 
     coll = db['vulnerabilities'] 
     logging.info('Connected to MongoDB') 
     basepath = os.path.dirname(__file__) 
     filepath = os.path.abspath(os.path.join(basepath, "..")) 
     archive_filepath = filepath + vuln_folder 
     filedir = os.chdir(archive_filepath) 
     file_count = 0 
     for item in os.listdir(filedir): 
      if item.endswith('.json'): 
       file_name = os.path.abspath(item) 
       with open(item, 'r') as currentfile: 
        vuln_counter = 0 
        duplicate_count = 0 
        logging.info('Currently processing ' + item) 
        file_count +=1 
        json_data = currentfile.read() 
        vuln_content = json.loads(json_data) 
        for vuln in vuln_content: 
         try: 
          del vuln['_type'] 
          coll.insert(vuln, continue_on_error=True) 
          vuln_counter +=1 
         except pymongo.errors.DuplicateKeyError: 
          duplicate_count +=1 

       logging.info('Added ' + str(vuln_counter) + ' vulnerabilities for ' + item) 
       logging.info('Found ' + str(duplicate_count) + ' duplicate records!') 
       os.remove(file_name) 
     logging.info('Processed ' + str(file_count) + ' files') 
    except Exception as e: 
     logging.exception(e) 

はまだ必要ありませんつのキーを削除しますが、そのキーは私が_sourceからサブキーを必要として何のために必要なデータを持っていません。私はこれを達成する最善の方法について確信が持てません。新しい情報でJSONファイルを再作成するだけでプログラム上正しいのかどうかはわかりますが、キーと構造の順序を保持して、レベル。

答えて

1

辞書update()機能を使用して、何をしようとしているのかを確認することができますが、辞書には「キーの順番」がありません - Key Order in Python Dictionariesを参照してください。

これを行う方法の1つは、辞書の定義から始まります。

d = { 
    "_index": "bulletins", 
    "_type": "bulletin", 
    "_id": "OPENWRT-SA-000001", 
    "_score": None, 
    "_source": { 
     "lastseen": "2016-09-26T15:45:23", 
     "references": [ 
      "http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2015-3193", 
     ], 
     "affectedPackage": [ 
      { 
       "OS": "OpenWrt", 
       "OSVersion": "15.05", 
       "packageVersion": "9.9.8-P3-1", 
       "packageFilename": "UNKNOWN", 
       "arch": "all", 
       "packageName": "bind", 
       "operator": "lt" 
      } 
     ], 
     "edition": 1, 
     "description": "value in here", 
     "reporter": "OpenWrt Project", 
     "published": "2016-01-24T13:33:41", 
     "title": "bind: Security update (4 CVEs)", 
     "type": "openwrt", 
     "bulletinFamily": "unix", 
     "cvelist": [ 
      "CVE-2015-8704", 
     ], 
     "modified": "2016-01-24T13:33:41", 
     "id": "OPENWRT-SA-000001", 
     "href": "https://lists.openwrt.org/pipermail/openwrt-security-announce/2016-January/000001.html", 
     "cvss": { 
      "score": 7.1, 
      "vector":  "AV:NETWORK/AC:MEDIUM/Au:NONE/C:NONE/I:NONE/A:COMPLETE/" 
     } 
    } 
} 

# create a new dictionary with everything except the key "_source" 
new_d = {key: d[key] for key in d if key != '_source'} 

# add the keys/values from "_source" to new dictionary 
new_d.update(d['_source']) # This will overwriting any existing keys 

new_dの出力:

{'_id': 'OPENWRT-SA-000001', 
'_index': 'bulletins', 
'_score': None, 
'_type': 'bulletin', 
'affectedPackage': [{'OS': 'OpenWrt', 
    'OSVersion': '15.05', 
    'arch': 'all', 
    'operator': 'lt', 
    'packageFilename': 'UNKNOWN', 
    'packageName': 'bind', 
    'packageVersion': '9.9.8-P3-1'}], 
'bulletinFamily': 'unix', 
'cvelist': ['CVE-2015-8704'], 
'cvss': { 
    'score': 7.1, 
    'vector': 'AV:NETWORK/AC:MEDIUM/Au:NONE/C:NONE/I:NONE/A:COMPLETE/'}, 
'description': 'value in here', 
'edition': 1, 
'href': 'https://lists.openwrt.org/pipermail/openwrt-security-announce/2016-January/000001.html', 
'id': 'OPENWRT-SA-000001', 
'lastseen': '2016-09-26T15:45:23', 
'modified': '2016-01-24T13:33:41', 
'published': '2016-01-24T13:33:41', 
'references': ['http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2015- 
3193'], 
'reporter': 'OpenWrt Project', 
'title': 'bind: Security update (4 CVEs)', 
'type': 'openwrt'} 
+0

を:d = currentfile.read() new_json = {key:キーの場合はキーのdキー[keyならば!= '_source'} new_json.update(d ['source']) vuln _content = json.loads(new_json) 'ですが、これは' TypeError:文字列インデックスは整数でなければなりません 'というエラーを返します。 – Luke

+1

'currentfile.read()'の出力を 'd'に代入したので、' d'は文字列。あなたがしたいことは、 'd = json.loads(currentfile.read())' – pault

+0

のようなものだったと思う。これは役に立つかもしれない:[辞書から項目を削除する](https://stackoverflow.com/questions/5844672 /辞書から項目を削除する) – pault

0

私はそれが次のコードを使用して作業を得ることができた:私はそれを変更することで、私の既存のコードでこれを実装しようとした

for vuln in vuln_content: 
        try: 
         del vuln['_type'] 
         new_vuln = {key: vuln[key] for key in vuln if key != '_source'} 
         new_vuln.update(vuln['_source']) 
         coll.insert(new_vuln, continue_on_error=True) 
         vuln_counter +=1 
        except pymongo.errors.DuplicateKeyError: 
         duplicate_count +=1