generateClass function

String generateClass(
  1. String className,
  2. Map<String, dynamic> def,
  3. Map<String, dynamic> allDefs
)

Implementation

String generateClass(
  String className,
  Map<String, dynamic> def,
  Map<String, dynamic> allDefs,
) {
  final props = (def['properties'] as Map?)?.cast<String, dynamic>() ?? {};
  final requiredList = (def['required'] is List)
      ? (def['required'] as List).cast<String>()
      : <String>[];

  final fields = <FieldSpec>[];
  for (final entry in props.entries) {
    final jsonKey = entry.key;
    final schema = (entry.value as Map).cast<String, dynamic>();
    String dartType = 'dynamic';
    if (schema[r'$ref'] is String) {
      dartType = refToName(schema[r'$ref'] as String);
    } else if (schema['type'] is String) {
      dartType = typeToDart(schema['type'] as String, schema);
    }

    final isRequired = requiredList.contains(jsonKey);
    final fieldName = sanitizeFieldName(jsonKey);
    fields.add(FieldSpec(
      fieldName: fieldName,
      jsonKey: jsonKey,
      type: isRequired ? dartType : '$dartType?',
      nullable: !isRequired,
      description: schema['description'] as String?,
    ));
  }

  final b = StringBuffer();

  // Doc
  b.writeln('class $className {');

  // Fields
  for (final f in fields) {
    if ((f.description ?? '').isNotEmpty) {
      b.writeln('  /// ${f.description}');
    }
    b.writeln('  final ${f.type} ${f.fieldName};');
  }

  // Additional properties: collect unknown keys if additionalProperties allowed
  final allowAdditional = def.containsKey('additionalProperties');
  if (allowAdditional) {
    b.writeln('  /// Unrecognized properties captured here.');
    b.writeln('  final Map<String, dynamic>? additionalProperties;');
  }
  b.writeln();

  // Constructor
  b.writeln('  const $className({');
  for (final f in fields) {
    final req = f.nullable ? '' : 'required ';
    b.writeln('    $req this.${f.fieldName},');
  }
  if (allowAdditional) {
    b.writeln('    this.additionalProperties,');
  }
  b.writeln('  });\n');

  // fromJson
  b.writeln('  factory $className.fromJson(Map<String, dynamic> json) {');
  if (allowAdditional) b.writeln('    final extras = <String, dynamic>{};');
  for (final f in fields) {
    final read = "json['${f.jsonKey}']";
    // Primitive / list / ref handling (shallow), try to detect $ref kinds
    String parse;
    if (f.type.endsWith('?')) {
      final base = f.type.substring(0, f.type.length - 1);
      parse = _jsonReadExpr(base, read, allDefs, false);
    } else {
      parse = _jsonReadExpr(f.type, read, allDefs, true);
    }
    b.writeln('    final _${f.fieldName} = $parse;');
  }

  // gather extras
  if (allowAdditional) {
    b.writeln('    for (final entry in json.entries) {');
    if (fields.isEmpty) {
      b.writeln('      extras[entry.key] = entry.value;');
    } else {
      final keys = fields.map((f) => "'${f.jsonKey}'").join(', ');
      b.writeln('      if (!{ $keys }.contains(entry.key)) {');
      b.writeln('        extras[entry.key] = entry.value;');
      b.writeln('      }');
    }
    b.writeln('    }');
  }

  b.writeln('    return $className(');
  for (final f in fields) {
    b.writeln('      ${f.fieldName}: _${f.fieldName},');
  }
  if (allowAdditional) {
    b.writeln('      additionalProperties: extras.isEmpty ? null : extras,');
  }
  b.writeln('    );');
  b.writeln('  }\n');

  // toJson
  b.writeln('  Map<String, dynamic> toJson() {');
  b.writeln('    final _json = <String, dynamic>{};');
  for (final f in fields) {
    final writeExpr = _jsonWriteExpr(f.type, f.fieldName, allDefs);
    if (f.nullable) {
      b.writeln("    if (${f.fieldName} != null) {");
      b.writeln("      _json['${f.jsonKey}'] = $writeExpr;");
      b.writeln('    }');
    } else {
      b.writeln("    _json['${f.jsonKey}'] = $writeExpr;");
    }
  }
  if (allowAdditional) {
    b.writeln('    if (additionalProperties != null) {');
    b.writeln('      _json.addAll(additionalProperties!);');
    b.writeln('    }');
  }
  b.writeln('    return _json;');
  b.writeln('  }');

  b.writeln('}\n');
  return b.toString();
}