编写API时,我经常需要从嵌套的JSON中初始化类,如
"Resources": {
"MyCluster": {
"Type": "AWS::EMR::Cluster",
"Properties": {
"Applications": [
{ "Name" : "Hadoop" },
{ "Name" : "SPARK" },
{ "Name" : "Ganglia" }
],
"BootstrapActions" : [...],
"Instances": {
"AdditionalMasterSecurityGroups" : [{ "Fn::GetAtt" : ["rAllowJupyter","GroupId"] }],
"Ec2KeyName" : { "Ref" : "EC2KeyName" },
"Ec2SubnetId" : { "Ref" : "Subnet" },
"MasterInstanceGroup": {
"InstanceCount": 1,
"InstanceType": { "Ref" : "InstanceType" }
},
"CoreInstanceGroup": {
"InstanceCount": { "Ref" : "CoreNodeCount" },
"InstanceType": { "Ref" : "InstanceType" }
}
},
"Configurations": [...],
"Name": "MyCluster",
"JobFlowRole": "EMR_EC2_DefaultRole",
"ServiceRole": "EMR_DefaultRole",
"ReleaseLabel": "emr-4.6.0",
"LogUri": "s3://path/to/logs/",
"Tags": [
{ "Key": "Name", "Value": "aqa-spark"},
{ "Key": "Owner", "Value": { "Ref" : "OwnerTag" }},
{ "Key": "Purpose", "Value": { "Ref" : "PurposeTag" }}
]
}
}
},
在我的代码中,这导致级联
# When my API receives such a ...
n_json = {"nested1": {"nested2" : { "nested3" : "..." }}}
# .. I need to instantiate a proper object out of it ...
nested1 = Nested1.from_json(json.loads(n_json))
# ... so I can later use the instance in OOP style.
nested1.nested2.run_an_intance_method()
对于每一层嵌套,这都会产生更多的重复性并且容易出错。有什么聪明的方法吗?
答案 0 :(得分:1)
这是你如何从JSON创建一个嵌套对象(类似于PHP的方式)。要从JSON创建对象树(而不是解析JSON,这只是一个Python结构),请编写以下类:
class Nested:
def __new__(cls, structure):
self = super(Nested, cls).__new__(cls)
if type(structure) is dict:
self.__dict__ = {key: Nested(structure[key]) for key in structure}
elif type(structure) is list:
self = [Nested(item) for item in structure]
else:
self = structure
return self
并从解析的JSON中调用它。例如:
import json
s = json.dumps({'a': 1, 'b': {'c': [1, 2, {'d': 3}], 'e': {'f': 'g'}}})
result = Nested(json.loads(s))
print(result.a) # 1
print(result.b.c) # [1, 2, <__main__.Nested object at 0x00000297A983D828>]
print(result.b.c[0]) # 1
print(result.b.c[2].d) # 3
以下是该课程的工作原理:
__new__
。这里我们构造一个对象的实例(空)
如果new是list,我们将self替换为嵌套对象列表,以便Nested({'a': [1, 2, 3]).a
等于[Nested(1), Nested(2), Nested(3)]
(也等于[1, 2, 3]
,见数字4 )
如果new是dict,我们会为每个键创建一个具有相同名称的属性,并为其指定Nested(dict[key])
。
如果是其他任何类型,只需为self指定值(将self
替换为值),以便Nested({'a': ['b', 'c', 'd']}).a[0]
等于'b'
,而不是Nested(..)