How to deserialize a string into a dict with json loads with unknown function?
Question:
When I have a string like this
test = '{"key1":"value1", "key2": UnknownFunction("value2")}'
I cannot use json.loads
to deserialize its content as the serialized data object contains an unknown function. Is there a simple way to map such a function (or any unknown function) to e.g. str
, so that I can deserialize the data object to get a dict like
{"key1":"value1", "key2": "value2"}
?
The following code is working but maybe there is some better way?
for removable in ["UnknownFunction"]:
test= test.replace(removable + "(", "")
test = test.replace(")", "")
data = json.loads(test)
Answers:
You could make use of ast.literal_eval
using your own NodeTransformer
to handle function calls:
import ast
class Transformer(ast.NodeTransformer):
def generic_visit(self, node):
super().generic_visit(node)
if isinstance(node, ast.Call):
_args = node.args
return _args if len(_args) > 0 else ast.Constant(value='null')
return node
def transform_eval(py_str):
return ast.literal_eval(Transformer().visit(ast.parse(py_str,
mode='eval')).body)
testStr = """ {
"key1": "value1",
"key2": UnknownFunction("value1"),
"key3": foo(),
}"""
print(transform_eval(testStr.strip()))
Out:
{'key1': 'value1', 'key2': 'value1', 'key3': 'null'}
Note:
I haven’t checked if all possible function argument combinations work: UnknownFunction("value1", foo="bar")
or UnknownFunction(*args, foo="bar")
When I have a string like this
test = '{"key1":"value1", "key2": UnknownFunction("value2")}'
I cannot use json.loads
to deserialize its content as the serialized data object contains an unknown function. Is there a simple way to map such a function (or any unknown function) to e.g. str
, so that I can deserialize the data object to get a dict like
{"key1":"value1", "key2": "value2"}
?
The following code is working but maybe there is some better way?
for removable in ["UnknownFunction"]:
test= test.replace(removable + "(", "")
test = test.replace(")", "")
data = json.loads(test)
You could make use of ast.literal_eval
using your own NodeTransformer
to handle function calls:
import ast
class Transformer(ast.NodeTransformer):
def generic_visit(self, node):
super().generic_visit(node)
if isinstance(node, ast.Call):
_args = node.args
return _args if len(_args) > 0 else ast.Constant(value='null')
return node
def transform_eval(py_str):
return ast.literal_eval(Transformer().visit(ast.parse(py_str,
mode='eval')).body)
testStr = """ {
"key1": "value1",
"key2": UnknownFunction("value1"),
"key3": foo(),
}"""
print(transform_eval(testStr.strip()))
Out:
{'key1': 'value1', 'key2': 'value1', 'key3': 'null'}
Note:
I haven’t checked if all possible function argument combinations work: UnknownFunction("value1", foo="bar")
or UnknownFunction(*args, foo="bar")