Scenario
Once upon a time, there was this human (ahem, me, ahem) who tried (and succeeded) to build a small program which would convert JSON to a MSSQL query using Python 3.x.
How does it work?
The user makes a POST request with a JSON (in the code, I've used a JSON file) which looks like this:
{
"endpoint": "rfc",
"expression": [
{
"field": "first_name",
"operator": "EQ",
"value": "Dixie"
},
"AND",
[
{
"field": "last_name",
"operator": "NEQ",
"value": "Smith"
},
"OR",
{
"field": "middle_name",
"operator": "EQ",
"value": "Sam"
}
]
],
"limit": "2"
}
Now, the key point in this story is the expression
which is being translated to a query, using recursion, as follows:
def process(data):
"""
:param data: JSON Object (dict).
:return: where clause (str) built from data
"""
where_clause = ""
if isinstance(data, list):
for part in data:
if part not in LOGICAL_OPERATORS:
where_clause += " ({}) ".format(process(part))
else:
where_clause += process(part)
elif isinstance(data, dict):
where_clause += " {} {} '{}'".format(data["field"], COMPARISON_OPERATORS[data["operator"]], data["value"])
elif isinstance(data, str):
return data
return where_clause
The entire code, is as follows:
import json
LOGICAL_OPERATORS = ("AND", "OR")
COMPARISON_OPERATORS = {
"LT": "<",
"GT": ">",
"LTE": "<=",
"GTE": ">=",
"EQ": "=",
"NEQ": "!="
}
def get_data(file):
"""
:param file: JSON file.
:return: data as a json object (dict).
"""
with open(file) as data_file:
return json.load(data_file)
def process(data):
"""
:param data: JSON Object (dict).
:return: where clause (str) built from data
"""
where_clause = ""
if isinstance(data, list):
for part in data:
if part not in LOGICAL_OPERATORS:
where_clause += " ({}) ".format(process(part))
else:
where_clause += process(part)
elif isinstance(data, dict):
where_clause += " {} {} '{}'".format(data["field"], COMPARISON_OPERATORS[data["operator"]], data["value"])
elif isinstance(data, str):
return data
return where_clause
def main():
expression = get_data("other.json")["expression"]
where_clause = process(expression)
return "SELECT * FROM table WHERE {}".format(where_clause)
if __name__ == '__main__':
print(main())
Questions:
- Will the recursive function scale good on a larger
expression
? Now, thatexpression
can go in depth as long as the memory goes. Should I add a limit to it? - Did I miss something? Maybe an edge case?
- Is there an already builtin in out there for this?