generateModelClass function
Implementation
bool generateModelClass(
String srcDir,
String distDir,
String tag, {
required bool nullable,
}) {
const metaTag = "@meta";
if (srcDir.endsWith("/")) srcDir = srcDir.substring(0, srcDir.length - 1);
if (distDir.endsWith("/")) distDir = distDir.substring(0, distDir.length - 1);
final src = Directory(srcDir);
final fileList = src.listSync(recursive: true);
String indexFile = "";
if (fileList.isEmpty) return false;
if (!Directory(distDir).existsSync()) {
Directory(distDir).createSync(recursive: true);
}
File file;
fileList.forEach((f) {
if (FileSystemEntity.isFileSync(f.path)) {
file = File(f.path);
final paths = path.basename(f.path).split(".");
final String fileName = paths.first;
if (paths.last.toLowerCase() != "json" || fileName.startsWith("_"))
return;
final dartFilePath = f.path
.replaceFirst(srcDir, distDir)
.replaceFirst(RegExp('.json', caseSensitive: false), ".dart");
final map = json.decode(file.readAsStringSync()) as Map<String, dynamic>;
// To ensure that import statements are not repeated,
// we use Set to save import statements
final importSet = Set<String>();
//Create a case-insensitive Map for the meta data of Json file
final meta = LinkedHashMap<String, dynamic>(
equals: (a, b) => a.toLowerCase().trim() == b.toLowerCase().trim(),
hashCode: (k) => k.toLowerCase().hashCode,
);
// Get the meta data of Json file
if (map[metaTag] != null) {
meta.addAll(map[metaTag] as Map<String, dynamic>);
map.remove(metaTag);
}
//generated class name
String? className = meta['className'] as String?;
if (className == null || className.isEmpty) {
className = fileName[0].toUpperCase() + fileName.substring(1);
}
//set ignore
final bool ignore = (meta['ignore'] ?? false) as bool;
if (ignore) {
print('skip: ${f.path}');
indexFile = exportIndexFile(dartFilePath, distDir, indexFile);
return;
}
//handle imports
final List imports = (meta['import'] ?? []) as List;
imports.forEach((e) => importSet.add("import '$e'"));
//set nullable
final bool _nullable = (meta['nullable'] ?? nullable) as bool;
// comments for Json fields
final comments = meta['comments'] ?? {};
// Handle fields in Json file
final StringBuffer fields = StringBuffer();
map.forEach((key, v) {
key = key.trim();
if (key.startsWith("_")) return;
if (key.startsWith("@")) {
if (comments[v] != null) {
_writeComments(comments[v],fields);
}
fields.write(key);
fields.write(" ");
fields.write(v);
fields.writeln(";");
} else {
final bool optionalField = key.endsWith('?');
final bool notNull = key.endsWith('!');
if (optionalField || notNull) {
key = key.substring(0, key.length - 1);
}
final bool shouldAppendOptionalFlag =
!notNull && (optionalField || _nullable);
if (comments[key] != null) {
_writeComments(comments[key],fields);
}
if (!shouldAppendOptionalFlag) {
fields.write('late ');
}
fields.write(getDataType(v, importSet, fileName, tag));
if (shouldAppendOptionalFlag) {
fields.write('?');
}
fields.write(" ");
fields.write(key);
//new line
fields.writeln(";");
}
//indent
fields.write(" ");
});
var dist = replaceTemplate(tpl, [
fileName,
className,
className,
fields.toString(),
className,
className,
className
]);
// Insert the imports at the head of dart file.
var _import = importSet.join(";\r\n");
_import += _import.isEmpty ? "" : ";";
dist = dist.replaceFirst("%t", _import);
//Create dart file
File(dartFilePath)
..createSync(recursive: true)
..writeAsStringSync(dist);
indexFile = exportIndexFile(dartFilePath, distDir, indexFile);
print('done: ${f.path} -> $dartFilePath');
}
});
if (indexFile.isNotEmpty) {
final p = path.join(distDir, "index.dart");
File(p).writeAsStringSync(indexFile);
print('create index file: $p');
}
return indexFile.isNotEmpty;
}