# Get json format from sqlalchemy class

I have written a small tool to generate a json file from sqlalchemy models files to automate the tedious procedure of writing all the sql raws in a json format. The script works, but there are few parts, see get_modules function, that can be improved. I would be glad to have a review of this code. Thanks

# -*- coding: utf-8 -*-

import os
import sys
import glob

PATH = sys.argv[1]
output_filename = 'en.json'

intro = ("""
{
"sidebar": {
"overview": "Overview",
},
"title": "title"
},
"welcome": {
"title": "Welcome to the prototype app!"
},

""")

def get_fields(input_filename):
"""It returns all fields of a model in a list"""
fields = []
endpoint = None
with open(PATH+input_filename, 'r') as inputfile:
for line in inputfile:
if '__plural_name__' in line:
endpoint = line.split('=')[1].strip().replace("'","")
if '= Column' in line:
fields.append(line.split()[0])
return endpoint, fields

def get_modules():
"""It returns a list of all models"""
files = []
cwd = os.getcwd()
os.chdir(PATH)
files = glob.glob("*.py")
os.chdir(cwd)
return files

if __name__ == "__main__":

models = get_modules()
target = open(output_filename, 'w')
target.write(intro)
for m in models:
if m != '__init__.py':
end_name, attrs = get_fields(m)
target.write('  "{}": {{\n'.format(end_name))
target.write('    "title": "{}",\n'.format(end_name))
target.write('    "fields": {\n')
for a in attrs:
target.write('      "{}": "{}",\n'.format(a,a))
target.write('    }\n')
target.write('  },\n')
target.close()


You should take advantage of what is already available. For example, the json module. Instead of putting the string together manually, use json.dumps. Python doesn't have a SQLAlchemy library built-in, but you can get one on PyPI, just pip install SQLAlchemy. Using this, you can browse https://stackoverflow.com/q/5022066/5827958 to see some simple ways of converting SQLAlchemy to JSON.

You define files = [] in get_modules(). That's unnecessary. Python does not need you to declare variables before using them. Just save yourself that tiny bit of processing time, and take it out.

You can also make use of os.path, a built-in pointer to an OS-specific filesystem path module. In get_modules(), you can simplify down to:

def get_modules():
return glob.glob(os.path.join(PATH, "*.py"))


Since that now returns an absolute path instead of a relative one, you can now use merely input_filename instead of PATH+input_filename in get_fields().

I would also define get_modules as taking an argument for its path. That way, an importing module can use it for whatever path it wants, but your if __name__ == '__main__' block will give it sys.argv[1]. Since I just changed your function to using absolute paths, get_fields() doesn't need to know about PATH at all. On the side, you shouldn't be reading sys.argv unless __name__ == '__main__' anyway.

The purpose of your file is to convert, but an importing module has no access to the conversion code. I would suggest defining a function for the conversion, and then let the if __name__ == "__main__" block call that function with sys.argv[1] as an argument.

I'm glad that you use a with block in get_fields(), but I see you aren't in your main code. This could cause unexpected problems if something unexpected happened. You should open a file without a with block only in very rare cases.

• thanks a lot for your review. It is really helpful. I will first try to adjust my code, then look at other examples to convert sqlalchemy into json and see if I can use them for what I need Apr 12 '17 at 19:28