2017-05-04 3 views
1

Ich habe json wie untenKonvertieren von Nested Json in Python Objekt

verschachtelt
{ 
"product" : "name", 
"protocol" : "scp", 
"read_logs" : { 
    "log_type" : "failure", 
    "log_url" : "htttp:url" 
    } 
} 

Ich versuche, Python-Klasse-Objekt mit dem folgenden Code zu erstellen.

import json 
class Config (object): 
    """ 
    Argument: JSON Object from the configuration file. 
    """ 
    def __init__(self, attrs): 
     if 'log_type' in attrs: 
      self.log_type = attrs['log_type'] 
      self.log_url = attrs['log_url'] 
     else: 
      self.product = attrs["product"] 
      self.protocol = attrs["protocol"] 
    def __str__(self): 
     return "%s;%s" %(self.product, self.log_type) 

    def get_product(self): 
     return self.product 

    def get_logurl(self): 
     return self.log_url 

class ConfigLoader (object): 
    ''' 
     Create a confiuration loaded which can read JSON config files 
    ''' 
    def load_config (self, attrs): 
     with open (attrs) as data_file: 
      config = json.load(data_file, object_hook=load_json) 
     return config 

def load_json (json_object): 
    return Config (json_object) 

loader = ConfigLoader() 
config = loader.load_config('../config/product_config.json') 

print config.get_protocol() 

Aber wird der object_hook die load_json Aufruf rekursiv und die Klasse Config init genannt zweimal wird. Das endgültige Objekt, das ich erstellt habe, enthält daher nicht die verschachtelten JSON-Daten.

Gibt es eine Möglichkeit, das gesamte verschachtelte JSON-Objekt in einer einzigen Python-Klasse zu lesen?

Dank

Antwort

1

Eine Variation Pankaj Singhal Idee, sondern eine „generische“ Namespace-Klasse statt namedtuples mit:

import json 

class Generic: 
    @classmethod 
    def from_dict(cls, dict): 
     obj = cls() 
     obj.__dict__.update(dict) 
     return obj 

data = '{"product": "name", "read_logs": {"log_type": "failure", "log_url": "123"}}' 

x = json.loads(data, object_hook=Generic.from_dict) 
print(x.product, x.read_logs.log_type, x.read_logs.log_url) 
2

namedtuple & object_hook kann ein Einzeiler helfen schaffen:

# Create an object with attributes corresponding to JSON keys. 
def json_to_obj(data): return json.loads(data, object_hook=lambda converted_dict: namedtuple('X', converted_dict.keys())(*converted_dict.values())) 

oder erstellen Sie eine besser lesbare Funktion wie unten:

def _object_hook(converted_dict): return namedtuple('X', converted_dict.keys())(*converted_dict.values()) 
def json_to_obj(data): return json.loads(data, object_hook=_object_hook) 

Unten ist der Code-Schnipsel zu verwenden es:

import json 
from collections import namedtuple 

data = '{"product": "name", "read_logs": {"log_type": "failure", "log_url": htttp:url}}' 

x = json_to_obj(data) 
print x.product, x.read_logs.log_type, x.read_logs.log_url 

HINWEIS: Check out namedtuple ‚s rename parameter.

+0

namedtuples Verwendung ist nicht die semantisch beste Option, keine neue 'namedtuple's Schaffung zu erwähnen ziemlich ist langsam aufgrund der Klassenerstellung. – AKX