2017-02-21 89 views
0

所以我想要做的是使用預先存在的文件在python中反向工程JSON對象。文件內容如下所示:創建一個符合python中特定JSON的JSON對象

[ 
{ 
    "id": "PA_vnf", 
    "name": "PA", 
    "short-name": "PA", 
    "description": "A firewall PaloAlto", 
    "version": "1.0", 
    "connection-point": [ 
     { 
      "type": "VPORT", 
      "name": "PA/cp0" 
     }, 
     { 
      "type": "VPORT", 
      "name": "PA/cp1" 
     }, 
     { 
      "type": "VPORT", 
      "name": "PA/cp2" 
     } 
    ], 
    "vdu": [ 
     { 
      "id": "pa_vdu", 
      "external-interface": [ 
       { 
        "virtual-interface": { 
         "type": "VIRTIO" 
        }, 
        "vnfd-connection-point-ref": "PA/cp0", 
        "name": "eth0" 
       }, 
       { 
        "virtual-interface": { 
         "type": "VIRTIO" 
        }, 
        "vnfd-connection-point-ref": "PA/cp1", 
        "name": "eth1" 
       }, 
       { 
        "virtual-interface": { 
         "type": "VIRTIO" 
        }, 
        "vnfd-connection-point-ref": "PA/cp2", 
        "name": "eth2" 
       } 
      ], 
      "guest-epa": { 
       "cpu-pinning-policy": "ANY" 
      }, 
      "name": "vdu-1", 
      "vm-flavor": { 
       "storage-gb": 40, 
       "memory-mb": 4096, 
       "vcpu-count": 4 
      }, 
      "image": "paloAlto_RIP" 
     } 
    ], 
    "service-function-chain": "UNAWARE", 
    "meta": "important info" 
} 
] 

只是把事情簡單化,對於現在我硬編碼的所有鍵的值,如下圖所示的代碼示例:

def create_vnf_new(): 
    ginfo = nested_dict(5,list) 
    ginfo['description'] = 'A firewall PaloAlto' 
    ginfo['name'] = 'PA' 
    ginfo['id']= 'PA_vnf' 
    ginfo['version'] = '1.0' 
    ginfo['service-function-chain'] = 'UNAWARE' 
    ginfo['short-name'] = 'PA' 
    ginfo['vdu']['id'] = 'pa_vdu' 
    ginfo['vdu']['name'] = 'vdu-1' 
    ginfo['vdu']['image'] = 'paloAlto_RIP' 
    ginfo['vdu']['guest-epa']['cpu-pinning-policy'] = 'ANY' 
    ginfo['vdu']['external-interface']['virtual-interface']['type'] = 'VIRTIO' 
    ginfo['vdu']['external-interface']['vnfd-connection-point-ref'] = "PA/cp0" 
    ginfo['vdu']['external-interface']['name'] = 'eth0' 
    ginfo['vdu']['vm-flavor']['storage-gb'] = 20 
    ginfo['vdu']['vm-flavor']['memory-mb'] = 1024 
    ginfo['vdu']['vm-flavor']['vcpu-count'] = 4 
    print(json.dumps(ginfo)) 

def nested_dict(n, type): 
    if n == 1: 
    return defaultdict(type) 
    else: 
    return defaultdict(lambda: nested_dict(n-1, type)) 

爲此我得到下面的O/P:

{ 
"short-name": "PA", 
"vdu": { 
    "name": "vdu-1", 
    "image": "paloAlto_RIP", 
    "id": "pa_vdu", 
    "external-interface": { 
     "virtual-interface": { 
      "type": "VIRTIO" 
     }, 
     "vnfd-connection-point-ref": "PA/cp0", 
     "name": "eth0" 
    }, 
    "guest-epa": { 
     "cpu-pinning-policy": "ANY" 
    }, 
    "vm-flavor": { 
     "storage-gb": 20, 
     "vcpu-count": 4, 
     "memory-mb": 1024 
    } 
}, 
"description": "A firewall PaloAlto", 
"version": "1.0", 
"service-function-chain": "UNAWARE", 
"id": "PA_vnf", 
"name": "PA" 
} 

以上的O/P是完全正常的,但我想某些屬性,如「外部接口」有哪些我不能夠做多個值。我嘗試了字典上的append方法,但它一直在拋出錯誤「'collections.defaultdict'object has no attribute'append''。 示例追加我使用:ginfo ['vdu'] ['external-interface'] ['vnfd-connection-point-ref']。append(「value」)

我不確定發生了什麼問題。另外我如何獲得輸出中的第一個方括號,這在我的o/p中是缺少的。我知道它應該是一個數組,但是,我不知道如何應用我的字典對象上的數組邏輯。

如果解釋不夠清楚,請讓我知道,因爲我在約5個小時的運氣過後輸入此幫助。

回答

0

Python表現:

ginfo['vdu'] = [] 
interfaces = [] 
interfaces.append({'virtual-interface': {'type': 'VIRTIO'}, 
        'vnfd-connection-point-ref': 'PA/cp0', 
        'name': 'eth0'}) 
... 
... 

ginfo['vdu'].append({'id': 'pa_vdu', 
        'external-interface': interfaces}) 

使用json.loads的逆向工程結構更清晰:

>>> pprint(json.loads(json_string)) 
[{u'connection-point': [{u'name': u'PA/cp0', u'type': u'VPORT'}, 
         {u'name': u'PA/cp1', u'type': u'VPORT'}, 
         {u'name': u'PA/cp2', u'type': u'VPORT'}], 
    u'description': u'A firewall PaloAlto', 
    u'id': u'PA_vnf', 
    u'meta': u'important info', 
    u'name': u'PA', 
    u'service-function-chain': u'UNAWARE', 
    u'short-name': u'PA', 
    u'vdu': [{u'external-interface': [{u'name': u'eth0', 
            u'virtual-interface': {u'type': u'VIRTIO'}, 
            u'vnfd-connection-point-ref': u'PA/cp0'}, 
            {u'name': u'eth1', 
            u'virtual-interface': {u'type': u'VIRTIO'}, 
            u'vnfd-connection-point-ref': u'PA/cp1'}, 
            {u'name': u'eth2', 
            u'virtual-interface': {u'type': u'VIRTIO'}, 
            u'vnfd-connection-point-ref': u'PA/cp2'}], 
      u'guest-epa': {u'cpu-pinning-policy': u'ANY'}, 
      u'id': u'pa_vdu', 
      u'image': u'paloAlto_RIP', 
      u'name': u'vdu-1', 
      u'vm-flavor': {u'memory-mb': 4096, 
          u'storage-gb': 40, 
          u'vcpu-count': 4}}], 
    u'version': u'1.0'}] 
0

您不需要在字典上應用數組邏輯。如果你想要一個數組(即列表),然後使用一個列表。在您的原始JSON中,connection_pointvdu均爲字典列表,external-interfacevdu

如果你真的還是想建立這個了一行行,你可以這樣做:

ginfo['vdu'] = [] 
ginfo['vdu'].append({}) 
ginfo['vdu'][0]['id'] = 'pa_vdu' 

0

謝謝@Daniel Roseman和@klashxx我能夠使用兩個解決方案來構建最終代碼。我已經把下面的代碼:

import json 
import yaml 
import sys 
from collections import defaultdict 

def nested_dict(n, type): 
    if n == 1: 
    return defaultdict(type) 
    else: 
    return defaultdict(lambda: nested_dict(n-1, type)) 

ginfo = nested_dict(5,list) 
ginfo = [] 
ginfo.append({}) 
ginfo[0]['description'] = 'A firewall PaloAlto' 
ginfo[0]['name'] = 'PA' 
ginfo[0]['id']= 'PA_vnf' 
ginfo[0]['version'] = '1.0' 
ginfo[0]['service-function-chain'] = 'UNAWARE' 
ginfo[0]['short-name'] = 'PA' 
ginfo[0]['vdu'] = [] 
interfaces = [] 
interfaces.append({'virtual-interface': {'type': 'VIRTIO'}, 
            'vnfd-connection-point-ref': 'PA/cp0', 
            'name': 'eth0'}) 
interfaces.append({'virtual-interface': {'type': 'VIRTIO'}, 
            'vnfd-connection-point-ref': 'PA/cp1', 
            'name': 'eth1'}) 
interfaces.append({'virtual-interface': {'type': 'VIRTIO'}, 
            'vnfd-connection-point-ref': 'PA/cp2', 
            'name': 'eth2'}) 
ginfo[0]['vdu'].append({'id': 'pa_vdu', 
       'name': 'vdu-1', 
     'image': 'paloAlto_RIP', 
       'guest-epa':{'cpu-pinning-policy': 'ANY'}, 
       'external-interface': interfaces, 
       'vm-flavor': {'storage-gb': 40, 
       'memory-mb': 4096, 
       'vcpu-count': 4}}) 
ginfo[0]['connection-point'] = [] 
cp =[] 
cp.append({'type': 'VPORT', 
    'name': 'PA/cp0'}) 
cp.append({'type': 'VPORT', 
    'name': 'PA/cp1'}) 
cp.append({'type': 'VPORT', 
    'name': 'PA/cp2'}) 
ginfo[0]['connection-point'].append({'connection-point': cp}) 
print(json.dumps(ginfo)) 

def nested_dict(n, type): 
    if n == 1: 
    return defaultdict(type) 
    else: 
    return defaultdict(lambda: nested_dict(n-1, type)) 

,它噴出了以下O/P:

- "short-name": PA vdu: - name: "vdu-1" image: paloAlto_RIP id: pa_vdu "external-interface": - "virtual-interface": type: VIRTIO "vnfd-connection-point-ref": "PA/cp0" name: eth0 - "virtual-interface": type: VIRTIO "vnfd-connection-point-ref": "PA/cp1" name: eth1 - "virtual-interface": type: VIRTIO "vnfd-connection-point-ref": "PA/cp2" name: eth2 "guest-epa": "cpu-pinning-policy": ANY "vm-flavor": "storage-gb": 40 "vcpu-count": 4 "memory-mb": 4096 description: "A firewall PaloAlto" "connection-point": - "connection-point": - type: VPORT name: "PA/cp0" - type: VPORT name: "PA/cp1" - type: VPORT name: "PA/cp2" version: "1.0" "service-function-chain": UNAWARE id: PA_vnf name: PA

這在技術上是正確的。現在問題在於雙引號。我不想爲屬性使用雙引號,但是對於值的雙引號很好。雙引號對於屬性隨機出現。 再次感謝您的幫助。自從原來的問題得到解答以來,我正在將其解決。