Home > Enterprise >  Maintain relationship between variables when saving to / loading from JSON
Maintain relationship between variables when saving to / loading from JSON

Time:02-23

Is there any way of saving a variable to a json file that gets saved as a variable and opened as a usable variable later:

import json

variable = 123
test = {
    1 : 1*variable,
    2 : 2*variable,
    3 : 3*variable
}

with open('json_data_Test.json', 'w') as outfile:
    json.dump(test,outfile)

variable = 200

with open('json_data_Test.json', 'r') as outfile:
    test2 = json.load (outfile)

print(test2)

Output: {'1': 123, '2': 246, '3': 369}

Desired Output: {'1': 200, '2': 400, '3': 600}

The aim is to when the json file is reopened and brought into a dictionary, the values are changeable based on the new value of variable.

CodePudding user response:

No, because the multiplication operation was calculated and the result of that operation was stored in your json, which has no idea what variable is.

In fact, integers aren't mutable, so even if you ignore the json part and stick to python, once you have set the value of variable = 123 and used it in another = variable, modifying variable isn't going to change the value of another.

If you know for sure that the three keys in your json dict are integer multiples of a single variable, you could calculate the value of the greatest common divisor using math.gcd(). Then, divide each value by this and multiply by the new value of variable.

with open('json_data_Test.json', 'r') as outfile:
    test2 = json.load (outfile)

old_variable = math.gcd(test2['1'], test2['2'])

for key in test2:
    test2[key] *= (variable / old_variable)

Now, test2 is {'1': 200.0, '2': 400.0, '3': 600.0}


If you cannot guarantee that the GCD of the values in your dict will be the old variable, you should probably change the output object to save the value of variable in your json:

variable = 123
out_obj = {
    "variable": variable,
    "test": {
       1 : 1*variable,
       2 : 2*variable,
       3 : 3*variable
    }
}

with open('json_data_Test.json', 'w') as outfile:
    json.dump(out_obj,outfile)

variable = 200

with open('json_data_Test.json', 'r') as outfile:
    in_obj = json.load(outfile)

old_variable = in_obj["variable"]
test2 = in_obj["test"]

for key in test2:
    test2[key] *= (variable / old_variable)

CodePudding user response:

If you need something generic, and you DO NOT TAKE ANY INPUT FROM AN UNTRUSTED USER, you can use python's eval, and save the values as strings which will later be reevaluated with the new value of variable.
I suggest something like this:

import json

variable = 123
test = {
    1 : '1*<variable>',
    2 : '2*<variable>',
    3 : '3*<variable>',
    4 : ['<variable> 5', '<variable> 6'],
}

with open('json_data_Test.json', 'w') as outfile:
    outfile.write(json.dumps(test))

variable = 200


def evaluate(d):
    # recursively go through every value of the dictionary, and replace the <variable> wildcard with it's value, and then use `eval`.
    if type(d) == str:
        return eval(d.replace('<variable>', str(variable)))
    
    for k, v in d.items():
        if type(v) in [list, tuple]:
            d[k] = [evaluate(i) for i in v]
        else:
            d[k] = evaluate(v)
    return d


with open('json_data_Test.json', 'r') as outfile:
    data = outfile.read()
    evaluated = evaluate(json.loads(data))
    print(evaluated)

Again, if you accept any sort of untrusted user input, avoid using this at all costs, as it will allow that user to run arbitrary python code, which is a huge security vulnerability.

  • Related