Reputation: 2888
I am working with a system that unfortunately; uses nested json objects with the same key name. Based on some input data based on 0 to n elements I need to create this object dynamically but not sure how to do this with python correctly.
Here is what my json looks like in this example there are 3 expressions..
{
"metricExpressionTemplate": {
"metricExpressionType": "Boolean",
"operator": {
"type": "PLUS"
},
"expression1": {
"metricExpressionType": "Boolean",
"operator": {
"type": "PLUS"
},
"expression1": {
"metricExpressionType": "Boolean",
"operator": {
"type": "PLUS"
},
"expression1": {
"metricExpressionType": "Boolean",
"operator": {
"type": "PLUS"
}
}
}
}
}
}
I've been trying to dynamically create this but even when I try to add it manually..
import json
expression_object = {}
template_object = {
"metricExpressionType": "Boolean",
"operator": {
"type": "PLUS"
},
}
expression_object["metricExpressionTemplate"]["expression1"] = template_object
expression_object["metricExpressionTemplate"]["expression1"]["expression1"] = template_object
print(json.dumps(expression_object))
I get an error saying "ValueError: Circular reference detected".
Now even if this did work imagine having to do this for 250 objects! In some type of for loop..
for i in range(0,200):
# Add Expression objects dynamically..
expression_object["metricExpressionType"]["expression1"] = template_object
There's no "get_json_root" or "append" method on a dict object that I am aware of. How the heck would I do this?
Upvotes: 0
Views: 1055
Reputation: 12025
Instead of assigning template_object
to ["metricExpressionTemplate"]["expression1"]
and ["metricExpressionTemplate"]["expression1"]["expression1"]
, use a factory method to generate new template objects each time. So:
import json
def newTemplateObject():
t = {
"metricExpressionType": "Boolean",
"operator": {
"type": "PLUS"
},
}
return t
expression_object = {}
expression_object["metricExpressionTemplate"] = newTemplateObject()
expression_object["metricExpressionTemplate"]["expression1"] = newTemplateObject()
expression_object["metricExpressionTemplate"]["expression1"]["expression1"] = newTemplateObject()
print(json.dumps(expression_object))
As for adding the template_object when you have an object of unknown depth, you could use a recursive method, with each call checking whether the object passed to it has a key "expression1":
def addExpression(obj):
if "expression1" in obj.keys():
addExpression(obj["expression1"])
else:
obj["expression1"] = newTemplateObject()
Upvotes: 1
Reputation: 357
The error is occurring because you are attempting to reuse the same object inside itself. This can be overcome by generating a new dictionary each time it is needed. Then this can be performed in a loop through a recursive system, for example:
import json
def get_contents():
return {
"metricExpressionType": "Boolean",
"operator": {
"type": "PLUS"
}
}
def add_contents(d, contents, remaining):
d['expression1'] = contents()
if remaining > 0:
add_contents(d['expression1'], contents, remaining - 1)
objects = []
templates = ['metricExpressionTemplate', 'b', 'c']
for template_name in templates:
d = {template_name: get_contents()}
add_contents(d, get_contents, 2)
objects.append(d)
print json.dumps(objects, indent=2)
Upvotes: 0