最近公司在推动跨平台开发,大佬们有意向使用Flutter编写App中的部分页面,于是自学了一波Flutter,但是在Flutter的学习过程中发现结合json_annotation库时,发现要写一个json解析文件实在太麻烦了,在使用过程中,发现网站json转dart,但是感觉使用起来还是比较麻烦,于是自己动手使用python编写了一个json转dart实体的脚本。并用工具解析编写了公司项目json解析。
运行之后的效果如下图所示:
执行之后,会根据json的内容,生成两个文件,一个.dart文件和一个.g.dart文件,这样就完成了一个json解析文件的生成。
main的代码如下所示:
if __name__ == '__main__':
parser = ArgParser();
param = parser.parserArgument();
os.chdir(param.getTarget());
if(param.getOnlyBuild() == True):
(BuildRunnerProcess()).run();
else:
(JsonParser()).parse()
main的代码很简单,首先是解析参数,然后切换到指定的工作目录,如果只做生成操作,则直接执行命令,生成文件,否则解析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作为默认文件名。
主要代码在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' ;
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);
else:
return 'dynamic';
def generate(self, jsonObj):
#生成dart文件
fileContent = '/// This File is Generated by ' + os.path.basename(sys.argv[0]) + ' and you SHOULD NOT MODIFY this file' + os.linesep + \
'/// UNLESS the property we not recognized named property(number) and mark on the top.' + os.linesep + os.linesep;
fileContent += self.__writeHeaderImport();
clsName = param.getName();
if(clsName == None):
clsName = 'AutoGenerated';
fileContent += self.__writePartAnnouncement(clsName)
self.__fileOperator.write(fileContent);
self.__generateRecursive(jsonObj, self.__getClassName(clsName));
#生成json解析文件
(BuildRunnerProcess()).run();
def __myCapitalize(self, name):
if(len(name) <= 0):
return name;
elif(len(name) == 1):
return name.capitalize();
return name[0:1].upper() + name[1:len(name)];
def __is_contain_chinese(self, check_str):
for ch in check_str:
if u'\u4e00' <= ch <= u'\u9fff':
return True
return False
def __getClassName(self, name):
if(param.getPrefix() == None or name.startswith(param.getPrefix())):
return self.__myCapitalize(name);
return param.getPrefix() + self.__myCapitalize(name);
def __generateRecursive(self, jsonObj, clsName):
if(type(jsonObj) != dict and type(jsonObj) != list):
print('');
print('\033[31m Json Parse Error. Exiting...');
print('');
exit();
fileContent = self.__writeClassHeader(clsName);
props = [];
for (key, value) in jsonObj.items():
if self.__is_contain_chinese(key):
fileContent += os.linesep + ' /// This property we not recognized' + os.linesep + \
' /// You MUST Modify it BY YOURSELF.' + os.linesep;
name = 'property' + str((len(props) + 1));
props.append(name);
fileContent += self.__writeProperty('dynamic', name);
else:
props.append(key);
fileContent += self.__writeProperty(self.__Encoding(key, value), key);
if(type(value) == dict and len(value.keys()) > 0):
self.__generateRecursive(value, self.__getClassName(key));
elif(type(value) == list and len(value) > 0):
#取最长的元素为参照对象
obj = None;
for i in range(0, len(value)):
dic = value[i];
if type(dic) == dict:
if obj == None:
obj = dic;
else:
if len(dic.keys()) > len(obj.keys()):
obj = dic;
if(type(obj) == dict):
self.__generateRecursive(obj, self.__getClassName(key));
fileContent += self.__writeConstruct(clsName, props);
fileContent += self.__writeFromJsonMethod(clsName);
fileContent += self.__writeToJsonMethod(clsName);
fileContent += self.__writeEnding();
self.__fileOperator.write(fileContent);
def __writePartAnnouncement(self, clsName):
fileContent = 'part \'' + self.__getClassName(clsName) + '.g.dart\';' + os.linesep + os.linesep;
return fileContent;
def __writeHeaderImport(self):
fileContent = 'import \'package:json_annotation/json_annotation.dart\';' + os.linesep + os.linesep;
return fileContent;
def __writeClassHeader(self, clsName):
fileContent = '@JsonSerializable(nullable: true)';
fileContent += os.linesep;
fileContent += 'class ' + clsName + ' {' + os.linesep;
return fileContent;
def __writeProperty(self, typeName, name):
fileContent = ' ' + typeName + ' ' + name + ';' + os.linesep;
return fileContent;
def __writeEnding(self):
fileContent = '}' + os.linesep + os.linesep;
return fileContent;
def __writeConstruct(self, clsName, props):
fileContent = os.linesep + ' ' + clsName + '({';
isFirst = True;
count = 0;
for (idx, p) in enumerate(props):
count = count + 1;
if isFirst:
fileContent += 'this.' + p;
isFirst = False;
else:
fileContent += ', this.' + p;
if count % 4 == 0 and idx != len(props):
fileContent += os.linesep + ' ';
fileContent += '});' + os.linesep + os.linesep;
return fileContent;
def __writeFromJsonMethod(self, clsName):
fileContent = ' factory ' + clsName + '.fromJson(Map json) => _$' + clsName + 'FromJson(json);';
fileContent += os.linesep;
return fileContent;
def __writeToJsonMethod(self, clsName):
fileContent = ' Map toJson() => _$' + clsName + 'ToJson(this);';
fileContent += os.linesep + os.linesep;
return fileContent;
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();
我们知道,如果需要使用json_serialization并使用flutter packages pub run build_runner build命令正确的生成文件,则一个dart文件必须要包含以下几个方面的内容:
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' ;
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);
else:
return 'dynamic';
根据value的类型转换为Dart的类型,普通类型可以直接转换,如果类型为一个数组,则取第一个数据做为解析对象,如果第一个数据为一个字典,因为之后会生成一个新的对象,此时可以直接返回之后生成的对象的类名的List对象,否则继续递归解析,直至类型编码结束。若类型无法解析,则返回一个dynamic,表示任意类型。
递归解析是最关键的一步,代码如下:
def __generateRecursive(self, jsonObj, clsName):
if(type(jsonObj) != dict and type(jsonObj) != list):
print('');
print('\033[31m Json Parse Error. Exiting...');
print('');
exit();
fileContent = self.__writeClassHeader(clsName);
props = [];
for (key, value) in jsonObj.items():
if self.__is_contain_chinese(key):
fileContent += os.linesep + ' /// This property we not recognized' + os.linesep + \
' /// You MUST Modify it BY YOURSELF.' + os.linesep;
name = 'property' + str((len(props) + 1));
props.append(name);
fileContent += self.__writeProperty('dynamic', name);
else:
props.append(key);
fileContent += self.__writeProperty(self.__Encoding(key, value), key);
if(type(value) == dict and len(value.keys()) > 0):
self.__generateRecursive(value, self.__getClassName(key));
elif(type(value) == list and len(value) > 0):
#取最长的元素为参照对象
obj = None;
for i in range(0, len(value)):
dic = value[i];
if type(dic) == dict:
if obj == None:
obj = dic;
else:
if len(dic.keys()) > len(obj.keys()):
obj = dic;
if(type(obj) == dict):
self.__generateRecursive(obj, self.__getClassName(key));
fileContent += self.__writeConstruct(clsName, props);
fileContent += self.__writeFromJsonMethod(clsName);
fileContent += self.__writeToJsonMethod(clsName);
fileContent += self.__writeEnding();
self.__fileOperator.write(fileContent);
写入一些基本的信息之后,根据上述说明,首先要写入类头部信息,然后遍历其中的key,不排除有不合法的key出现,但此处只判断了key是否包含中文,如果包含中文,则生成一个默认的属性名,并加以注释,告诉用户该key需要自己处理,否则写入属性。当检测到另外一个dict时,此时需要生成一个新的对象,首先写入原类中关于该对象的属性,然后暂停原类写入,递归从新写入dict对应的新类。如果检测到一个list,同样需要一个新类,但为了防止丢失key,我们选取最长的一个元素进行写入。最后加上构造函数
fromJson、toJson和结尾等,之后再把整个类写入到文件当中。
最后一步就是调用命令生成part文件,代码如下所示:
class BuildRunnerProcess:
def run(self):
cmd = 'flutter packages pub run build_runner build --delete-conflicting-outputs';
child = subprocess.Popen([cmd], shell = True, stdout = subprocess.PIPE);
while child.poll() == None:
print(child.stdout.readline());
print('Generate Dart File Complete, Exiting....');
print('File Path:' + '\033[31m ' + filePath + '\033[0m');
使用subprocess生成另外一个进程,调用命令并输出提示信息,生成结束之后返回文件路径,到此全部结束。
最终使用工具生成的结果文件如下图的所示:
/// This File is Generator by json2dart.py and you SHOULD NOT MODIFY this file
/// UNLESS the property we not recognized named property(number) and mark on the top.
import 'package:json_annotation/json_annotation.dart';
part 'YJRecommendItemsForYouModel.g.dart';
@JsonSerializable(nullable: true)
class YJTwoFontCategoryBo {
int categoryStatus;
int categoryLevel;
String categoryName;
int categoryId;
YJTwoFontCategoryBo({this.categoryStatus, this.categoryLevel, this.categoryName, this.categoryId
});
factory YJTwoFontCategoryBo.fromJson(Map<String, dynamic> json) => _$YJTwoFontCategoryBoFromJson(json);
Map<String, dynamic> toJson() => _$YJTwoFontCategoryBoToJson(this);
}
@JsonSerializable(nullable: true)
class YJThreeFontCategoryBo {
int categoryStatus;
int categoryLevel;
String categoryName;
int categoryId;
YJThreeFontCategoryBo({this.categoryStatus, this.categoryLevel, this.categoryName, this.categoryId
});
factory YJThreeFontCategoryBo.fromJson(Map<String, dynamic> json) => _$YJThreeFontCategoryBoFromJson(json);
Map<String, dynamic> toJson() => _$YJThreeFontCategoryBoToJson(this);
}
@JsonSerializable(nullable: true)
class YJFirstFontCategoryBo {
int categoryStatus;
int categoryLevel;
String categoryName;
int categoryId;
YJFirstFontCategoryBo({this.categoryStatus, this.categoryLevel, this.categoryName, this.categoryId
});
factory YJFirstFontCategoryBo.fromJson(Map<String, dynamic> json) => _$YJFirstFontCategoryBoFromJson(json);
Map<String, dynamic> toJson() => _$YJFirstFontCategoryBoToJson(this);
}
@JsonSerializable(nullable: true)
class YJFontCategoryWrapperBos {
YJTwoFontCategoryBo twoFontCategoryBo;
YJThreeFontCategoryBo threeFontCategoryBo;
YJFirstFontCategoryBo firstFontCategoryBo;
YJFontCategoryWrapperBos({this.twoFontCategoryBo, this.threeFontCategoryBo, this.firstFontCategoryBo});
factory YJFontCategoryWrapperBos.fromJson(Map<String, dynamic> json) => _$YJFontCategoryWrapperBosFromJson(json);
Map<String, dynamic> toJson() => _$YJFontCategoryWrapperBosToJson(this);
}
@JsonSerializable(nullable: true)
class YJSpuPropertyBoList {
int itemId;
int modifyTime;
String propertyName;
int propType;
String spuCode;
String propertyValue;
int propSort;
int propId;
int createTime;
int propSource;
YJSpuPropertyBoList({this.itemId, this.modifyTime, this.propertyName, this.propType
, this.spuCode, this.propertyValue, this.propSort, this.propId
, this.createTime, this.propSource});
factory YJSpuPropertyBoList.fromJson(Map<String, dynamic> json) => _$YJSpuPropertyBoListFromJson(json);
Map<String, dynamic> toJson() => _$YJSpuPropertyBoListToJson(this);
}
@JsonSerializable(nullable: true)
class YJItemExpandRedisBo {
List<YJSpuPropertyBoList> spuPropertyBoList;
int itemTuType;
String transparentImage;
dynamic perfectChoice;
String productSpot;
String limitTransparentImage;
int quanlityFiveHundred;
int dimensionPurchase;
YJItemExpandRedisBo({this.spuPropertyBoList, this.itemTuType, this.transparentImage, this.perfectChoice
, this.productSpot, this.limitTransparentImage, this.quanlityFiveHundred, this.dimensionPurchase
});
factory YJItemExpandRedisBo.fromJson(Map<String, dynamic> json) => _$YJItemExpandRedisBoFromJson(json);
Map<String, dynamic> toJson() => _$YJItemExpandRedisBoToJson(this);
}
@JsonSerializable(nullable: true)
class YJTuRelationList {
int itemId;
double skuPrice;
int itemMainType;
String skuCode;
int skuNum;
int relationId;
YJTuRelationList({this.itemId, this.skuPrice, this.itemMainType, this.skuCode
, this.skuNum, this.relationId});
factory YJTuRelationList.fromJson(Map<String, dynamic> json) => _$YJTuRelationListFromJson(json);
Map<String, dynamic> toJson() => _$YJTuRelationListToJson(this);
}
@JsonSerializable(nullable: true)
class YJTuList {
int itemId;
int skuStatus;
double bossAmount;
String tuName;
String specLevel1Val;
double teacherAmount;
double specPrice;
String tuCode;
int specStock;
int version;
List<YJTuRelationList> tuRelationList;
String skuSmallImg;
double partnerAmount;
YJTuList({this.itemId, this.skuStatus, this.bossAmount, this.tuName
, this.specLevel1Val, this.teacherAmount, this.specPrice, this.tuCode
, this.specStock, this.version, this.tuRelationList, this.skuSmallImg
, this.partnerAmount});
factory YJTuList.fromJson(Map<String, dynamic> json) => _$YJTuListFromJson(json);
Map<String, dynamic> toJson() => _$YJTuListToJson(this);
}
@JsonSerializable(nullable: true)
class YJItemBizWordsBo {
int mallImgType;
String simpleName;
String mallImg;
YJItemBizWordsBo({this.mallImgType, this.simpleName, this.mallImg});
factory YJItemBizWordsBo.fromJson(Map<String, dynamic> json) => _$YJItemBizWordsBoFromJson(json);
Map<String, dynamic> toJson() => _$YJItemBizWordsBoToJson(this);
}
@JsonSerializable(nullable: true)
class YJData {
String itemDetail;
int urlType;
int soldNumber;
int autoChangeLogistics;
double minCommission;
String serviceStateValue;
int likeCount;
int errorCode;
String limitDiscountStr;
String subtitle;
double taxPrice;
int commissionPoint;
int onlineTime;
int ifInvoice;
int taxType;
int isLike;
List<YJFontCategoryWrapperBos> fontCategoryWrapperBos;
String storeCode;
String errorMessage;
int maxBigImageIndex;
int activityItemStatus;
int areaWarehouseStatus;
int activityTotalStock;
int itemId;
int disabled;
int profitType;
int subType;
int isShowStock;
String fineImg;
int itemPurchaseMin;
int bankRate;
double maxPrice;
String itemImgBig;
int endTime;
String itemParameters;
List<String> bigImgList;
int categoryOrder;
int specialPushFlag;
int addressPurchase;
int isClearGoods;
int selected;
int packageType;
bool isSelfSupport;
int itemCategory;
int stockPercentage;
int shipmentsType;
int limitItemUV;
int brandId;
int itemSnapshotVersion;
int itemCategoryLevel3;
int itemCategoryLevel2;
int itemCategoryLevel1;
int isFirstOrderPrice;
YJItemExpandRedisBo itemExpandRedisBo;
int itemOrder;
int textCount;
int saleType;
String itemName;
int ifGuarantee;
String itemBrandName;
int itemType;
String shopCode;
int itemTextCount;
int isHotSale;
String activityName;
int activityTimesId;
int favoriteItemTopstatus;
int totalStock;
double minItemVipPrice;
int dailyPurchase;
String barCode;
int releaseTime;
int phonePurchase;
int userTextCount;
int markType;
String strBankRate;
int groupId;
int tradeMode;
int manageType;
int itemBrand;
int limitActivityId;
String activityDesc;
String businessCertifyImage;
int currentTime;
String itemImg;
int packageId;
double maxCommission;
List<YJTuList> tuList;
double itemVipPrice;
int sellPersons;
int itemPurchaseMax;
int serviceState;
double sCommission;
String purchaseNotice;
YJItemBizWordsBo itemBizWordsBo;
int itemChannel;
String itemImgSmall;
int isSkuList;
int stock;
int status;
int shipmentsTime;
int startTime;
String smallImgList;
double minPrice;
String userName;
String sellType;
double itemPrice;
double maxItemVipPrice;
bool isNewItem;
int hideProgress;
YJData({this.itemDetail, this.urlType, this.soldNumber, this.autoChangeLogistics
, this.minCommission, this.serviceStateValue, this.likeCount, this.errorCode
, this.limitDiscountStr, this.subtitle, this.taxPrice, this.commissionPoint
, this.onlineTime, this.ifInvoice, this.taxType, this.isLike
, this.fontCategoryWrapperBos, this.storeCode, this.errorMessage, this.maxBigImageIndex
, this.activityItemStatus, this.areaWarehouseStatus, this.activityTotalStock, this.itemId
, this.disabled, this.profitType, this.subType, this.isShowStock
, this.fineImg, this.itemPurchaseMin, this.bankRate, this.maxPrice
, this.itemImgBig, this.endTime, this.itemParameters, this.bigImgList
, this.categoryOrder, this.specialPushFlag, this.addressPurchase, this.isClearGoods
, this.selected, this.packageType, this.isSelfSupport, this.itemCategory
, this.stockPercentage, this.shipmentsType, this.limitItemUV, this.brandId
, this.itemSnapshotVersion, this.itemCategoryLevel3, this.itemCategoryLevel2, this.itemCategoryLevel1
, this.isFirstOrderPrice, this.itemExpandRedisBo, this.itemOrder, this.textCount
, this.saleType, this.itemName, this.ifGuarantee, this.itemBrandName
, this.itemType, this.shopCode, this.itemTextCount, this.isHotSale
, this.activityName, this.activityTimesId, this.favoriteItemTopstatus, this.totalStock
, this.minItemVipPrice, this.dailyPurchase, this.barCode, this.releaseTime
, this.phonePurchase, this.userTextCount, this.markType, this.strBankRate
, this.groupId, this.tradeMode, this.manageType, this.itemBrand
, this.limitActivityId, this.activityDesc, this.businessCertifyImage, this.currentTime
, this.itemImg, this.packageId, this.maxCommission, this.tuList
, this.itemVipPrice, this.sellPersons, this.itemPurchaseMax, this.serviceState
, this.sCommission, this.purchaseNotice, this.itemBizWordsBo, this.itemChannel
, this.itemImgSmall, this.isSkuList, this.stock, this.status
, this.shipmentsTime, this.startTime, this.smallImgList, this.minPrice
, this.userName, this.sellType, this.itemPrice, this.maxItemVipPrice
, this.isNewItem, this.hideProgress});
factory YJData.fromJson(Map<String, dynamic> json) => _$YJDataFromJson(json);
Map<String, dynamic> toJson() => _$YJDataToJson(this);
}
@JsonSerializable(nullable: true)
class YJRecommendItemsForYouModel {
int errorCode;
List<YJData> data;
bool success;
YJRecommendItemsForYouModel({this.errorCode, this.data, this.success});
factory YJRecommendItemsForYouModel.fromJson(Map<String, dynamic> json) => _$YJRecommendItemsForYouModelFromJson(json);
Map<String, dynamic> toJson() => _$YJRecommendItemsForYouModelToJson(this);
}
生成的文件统一放在一个叫做Models的目录下面,这样可以直接使用,当然也可以自己移到另外的目录结构中去。在实际的使用过程中,除了没有返回的字段和不合法的字段之外,并没有出现过其他的问题。我业余用Flutter重写了公司的很多页面,其中的json解析全都是用的自己的工具,同事说网上其实已经有人写了这样的插件了,当然限于本人水平,我这个工具并没有写的多好,但终究自己写的知根知底,相比其他的工具来,还是使用自己写的工具靠谱。
对比开头说的那个网站,我觉得我的json2Dart工具有以下几个优点:
最后演示一下用Flutter改写的公司项目的一点点页面吧,也算给自己半个多月以来的成果做个展示,但是由于公司的政策规定,不能上传任何与公司相关的代码或资料到外网,所以只能简单的做个展示。Flutter写的项目还是相当流畅的,估计以后会成为主流,不过公司最近在转向RN,所以最近都加紧学习RN了。
json2Dart
有兴趣的朋友可以一起研究,没兴趣的朋友可以无视。