Rest Model Generator

A Dart CLI tool that automatically generates Flutter/Dart models from API responses.

Simply provide an API URL and rest_model_generator fetches the response, analyzes the JSON structure, detects data types and nested objects, and generates clean Dart model classes with null safety, fromJson() and toJson() support.

✨ Features

  • πŸš€ Generate models directly from an API URL
  • πŸ” Automatically detect JSON data types
  • 🧩 Generate nested models
  • πŸ“„ Generate all models in a single Dart file
  • 🐍 Convert API field names to Dart camelCase
  • πŸ›‘οΈ Null-safe model generation
  • πŸ”„ Automatically merge fields from multiple objects
  • πŸ“₯ Generate fromJson()
  • πŸ“€ Generate toJson()
  • πŸ”’ Support String, int, double, bool
  • πŸ—οΈ Generate nested object models
  • ⚑ Simple CLI commands

πŸ“¦ Installation

Activate the package globally:

dart pub global activate rest_model_generator

Or add it as a development dependency:

dart pub add --dev rest_model_generator

πŸš€ Usage

Provide an API endpoint using the --url option:

dart run rest_model_generator --url https://api.restful-api.dev/objects

The generator will:

  1. Call the API.
  2. Read the JSON response.
  3. Analyze the response structure.
  4. Detect primitive and nested types.
  5. Merge fields from multiple objects.
  6. Convert JSON field names to Dart camelCase.
  7. Generate the Dart model.
  8. Add fromJson().
  9. Add toJson().

Generated files are currently written to:

lib/models/

Example:

lib/
└── models/
    └── product.dart

πŸ§ͺ Example API Response

Given an API response like:

[
  {
    "id": "1",
    "name": "Google Pixel 6 Pro",
    "data": {
      "color": "Cloudy White",
      "capacity": "128 GB"
    }
  },
  {
    "id": "2",
    "name": "Apple iPhone 12 Mini, 256GB, Blue",
    "data": null
  },
  {
    "id": "3",
    "name": "Apple iPhone 12 Pro Max",
    "data": {
      "color": "Cloudy White",
      "capacity GB": 512
    }
  }
]

The generator produces:

// GENERATED CODE - DO NOT MODIFY BY HAND

class Product {
  final String? id;
  final String? name;
  final ProductData? data;

  Product({
    this.id,
    this.name,
    this.data,
  });

  factory Product.fromJson(Map<String, dynamic> json) {
    return Product(
      id: json['id'] as String?,
      name: json['name'] as String?,
      data: json['data'] == null
          ? null
          : ProductData.fromJson(
              json['data'] as Map<String, dynamic>,
            ),
    );
  }

  Map<String, dynamic> toJson() {
    return {
      'id': id,
      'name': name,
      'data': data?.toJson(),
    };
  }
}

class ProductData {
  final String? color;
  final String? capacity;
  final int? capacityGb;

  ProductData({
    this.color,
    this.capacity,
    this.capacityGb,
  });

  factory ProductData.fromJson(Map<String, dynamic> json) {
    return ProductData(
      color: json['color'] as String?,
      capacity: json['capacity'] as String?,
      capacityGb: json['capacity GB'] as int?,
    );
  }

  Map<String, dynamic> toJson() {
    return {
      'color': color,
      'capacity': capacity,
      'capacity GB': capacityGb,
    };
  }
}

🐫 CamelCase Conversion

API keys are preserved for JSON serialization while Dart variable names are converted to camelCase.

For example:

API Key Dart Variable
first_name firstName
first-name firstName
CPU model cpuModel
Hard disk size hardDiskSize
capacity GB capacityGb
Screen size screenSize

The original API key is always preserved for fromJson() and toJson().

Example:

final String? cpuModel;

maps to:

json['CPU model']

and:

'CPU model': cpuModel

πŸ›‘οΈ Null Safety

The generator is designed to create defensive, null-safe models.

Generated fields are nullable:

final String? name;
final int? age;
final double? price;
final UserData? data;

This helps protect applications from APIs returning:

{
  "name": null
}

or:

{
  "name": "John"
}

or completely omitting a field.

πŸ”’ Type Detection

The generator automatically detects common JSON types.

String

{
  "name": "John"
}

Generates:

final String? name;

Integer

{
  "age": 25
}

Generates:

final int? age;

Double

{
  "price": 99.99
}

Generates:

final double? price;

Boolean

{
  "active": true
}

Generates:

final bool? active;

Nested Object

{
  "user": {
    "name": "John"
  }
}

Generates:

final User? user;

and:

class User {
  final String? name;
}

πŸ”„ JSON Serialization

Every generated model contains both:

fromJson()

final product = Product.fromJson(json);

toJson()

final json = product.toJson();

Nested objects are automatically handled:

data: json['data'] == null
    ? null
    : ProductData.fromJson(
        json['data'] as Map<String, dynamic>,
      ),

and:

'data': data?.toJson(),

πŸ“ Generated File Structure

The current generator creates a single model file:

lib/
└── models/
    └── product.dart

Nested classes are kept in the same file, so no additional model imports are required.

Example:

class Product {
  ...
}

class ProductData {
  ...
}

🧠 Schema Merging

When an API returns multiple objects with different fields, the generator combines the available fields into a single model.

For example:

[
  {
    "id": 1,
    "data": {
      "color": "White"
    }
  },
  {
    "id": 2,
    "data": {
      "price": 599.99
    }
  }
]

The generated model understands both fields:

class ProductData {
  final String? color;
  final double? price;
}

This makes the generator useful for APIs where different objects contain different properties.

πŸ–₯️ CLI Options

API URL

--url <url>

Example:

dart run rest_model_generator \
  --url https://api.example.com/users

Current command format

dart run rest_model_generator --url <API_URL>

🚧 Roadmap

The project is actively being developed.

Planned features include:

  • GET / POST / PUT / PATCH / DELETE API support
  • Request body support
  • Custom HTTP headers
  • Query parameters
  • List of objects
  • List of primitive values
  • Mixed/dynamic lists
  • Root-level list handling improvements
  • DateTime detection
  • Enum generation
  • copyWith()
  • == and hashCode
  • toString()
  • Custom output directory
  • Custom model/class names
  • Config file support
  • Custom naming strategies
  • json_serializable support
  • Freezed model generation
  • Authentication support
  • Better CLI argument parsing
  • Unit tests
  • More robust API/schema inference

🀝 Contributing

Contributions are welcome.

If you find a bug, have a feature request, or want to improve the generator, please open an issue or submit a pull request.

Before submitting a pull request, make sure the project builds successfully and existing tests continue to pass.

πŸ“„ License

This project is licensed under the MIT License.

See the LICENSE file for details.

⭐ Support

If you find rest_model_generator useful, consider giving the project a ⭐ and sharing it with other Flutter developers.


Built for Flutter developers who are tired of manually writing API models. πŸš€