最近公司在推动跨平台开发,大佬们有意向使用Flutter编写App中的部分页面,于是自学了一波Flutter,但是在Flutter的学习过程中发现结合json_annotation库时,发现要写一个json解析文件实在太麻烦了,在使用过程中,发现网站json转dart,但是感觉使用起来还是比较麻烦,于是自己动手使用python编写了一个json转dart实体的脚本。并用工具解析编写了公司项目json解析。
效果演示
运行之后的效果如下图所示:
执行之后,会根据json的内容,生成两个文件,一个.dart文件和一个.g.dart文件,这样就完成了一个json解析文件的生成。
从main开始
main的代码如下所示:
if __name__ == '__main__':
parser = ArgParser();
param = parser.parserArgument();
os.chdir(param.getTarget());
if(param.getOnlyBuild() == True):
(BuildRunnerProcess()).run();
else:
(JsonParser()).parse()
main的代码很简单,首先是解析参数,然后切换到指定的工作目录,如果只做生成操作,则直接执行命令,生成文件,否则解析json。
参数解析
可以看到,脚本的参数列表如上图所示,解析如下;
- -h:显示帮助列表
- -b:仅编译生成解析文件
- -u:根据给定的url,请求json数据
- -f:从文件读取json数据
- -j:从json字符串读取数据
- -d:指定Flutter项目目录
- -c:指定model的类名
- -p:指定类名的前缀,如果类名已经名含前缀,则不再取前缀
Json数据解析
整个json解析类,包括数据请求,json解析两步操作,代码如下所示:
class JsonParser(object):
def __init__(self):
self.__param = param;
self.__jsonObj = '';
def __requestJsonFromURL(self, url):
response = requests.get(url);
self.__jsonObj = response.text;
def __readJsonFromFile(self, path):
filePath = os.path.expanduser(path);
if filePath != None:
try:
with open(filePath, mode='r') as f:
jsonstr = f.readline();
if jsonstr != None:
self.__jsonObj += jsonstr;
finally:
f.close();
def __readJsonFromString(self):
jsonstr = raw_input(prompt='press ENTER to exit.');
while(len(jsonstr) > 0):
self.__jsonObj += jsonstr;
jsonstr = raw_input(prompt='press ENTER to exit.');
def parse(self):
if(self.__param.getMethod() == 1):
self.__requestJsonFromURL(self.__param.getArgument());
elif(self.__param.getMethod() == 2):
self.__readJsonFromFile(self.__param.getArgument());
elif(self.__param.getMethod() == 3):
self.__readJsonFromString();
else:
exit();
print('Json Contentes like this below:');
print('');
print('\033[31m' + self.__jsonObj + '\033[0m');
self.__parse();
def __parse(self):
print('');
print('Parsing Json URL, Please Wait...');
self.__jsonObj = json.loads(self.__jsonObj);
if(self.__jsonObj != None):
generator = DartGenerator();
generator.generate(self.__jsonObj);
else:
print('');
print('Incorrect Json String, Program Will be Exit...');
exit();
可以看到,支持3种方式读取json数据,从url请求,从文件读取,从字符串读取,从url请求使用了reqeusts库。其实这个类的作用就是读取json数据,然后将json数据传递给DartGenerator类生成dart文件。
文件操作
文件操作的代码如下所示:
class FileOperator:
def __init__(self):
global filePath;
target = os.path.join(param.getTarget(), 'lib');
if(os.path.exists(target) == False or os.path.isdir(target) == False):
raise Exception, 'Where is the lib Directory?';
target = os.path.join(target, 'Models');
if(os.path.exists(target) == False or os.path.isdir(target) == False):
os.mkdir(target);
if param.getName() == None:
if param.getPrefix() == None:
target = os.path.join(target, 'AutoGenerated.dart');
else:
target = os.path.join(target, param.getPrefix() + 'AutoGenerated.dart');
else:
if param.getPrefix() == None:
target = os.path.join(target, param.getName() + '.dart');
else:
target = os.path.join(target, param.getPrefix() + param.getName() + '.dart');
filePath = target;
# 清空文件
with open(filePath, 'w') as f:
f.truncate(0);
def write(self, content):
with open(filePath, 'a+') as f:
f.write(content);
该类首先检查指定目录是否为一个正确的Flutter项目目录,目前这里只是通过检查目录下是否有lib目录,如果没有的话,就当做指定目录不合格。最后如果没有指定文件,则使用AutoGenerated.dart作为默认文件名。
写入dart代码
主要代码在DartGenerator类中,解析后的json数据是一个dict,其实就是一个n叉树,DartGenerator的作用就是递归遍历n叉树,生成.dart文件,代码如下所示:
class DartGenerator:
def __init__(self):
self.__fileOperator = FileOperator();
def __getStandardizedObjName(self, name):
prefix = param.getPrefix();
if(prefix == None or name.startswith(prefix)):
return self.__myCapitalize(name);
return prefix + self.__myCapitalize(name);
def __Encoding(self, key, value):
if(type(value) == bool):
return 'bool';
elif(type(value) == int):
return 'int';
elif(type(value) == float):
return 'double';
elif(type(value) == str or type(value) == unicode):
return 'String';
elif(type(value) == list):
if(len(value) == 0):
return 'List<dynamic>';
fObj = value[0];
if(type(fObj) == dict):
return 'List<' + self.__getStandardizedObjName(key) + '>';
return 'List<' + self.__Encoding(key, fObj) + '>';
elif(type(value) == dict):
return self.__getStandardizedObjName(key