json_factory_generator 1.0.2 copy "json_factory_generator: ^1.0.2" to clipboard
json_factory_generator: ^1.0.2 copied to clipboard

A code generator that creates centralized, type-safe JSON factories for Dart models with automatic discovery and List<T> support.

JSON Factory Generator #

A powerful Dart code generator that creates centralized, type-safe JSON factories for your models. Automatically discovers classes annotated with @jsonModel and generates a unified JsonFactory with support for both single objects and List<T> parsing.

Pub Package Dart Version License: MIT

Requirements #

  • Dart SDK: >=3.5.2 <4.0.0

Features #

  • Zero runtime initialization - everything is compile-time generated
  • Type-safe JSON parsing - compile-time checking with proper generics
  • Auto-discovery - automatically finds all @JsonModel classes with fromJson method
  • List support - handles List<T> parsing with proper type casting
  • Flexible - works with manual fromJson or json_serializable generated methods
  • No forced dependencies - json_serializable is optional, not required
  • Configurable output - customize output path and filename
  • Error handling - clear error messages for debugging
  • Build integration - works seamlessly with build_runner
  • Platform support - supports all Dart platforms (Android, iOS, Web, Desktop)

Install #

Add to your pubspec.yaml:

dependencies:
  json_factory_annotation: ^1.0.0
  json_annotation: ^4.9.0  # Optional: if using json_serializable

dev_dependencies:
  json_factory_generator: ^1.0.0
  build_runner: ^2.7.0
  # Optional: if using json_serializable for code generation
  json_serializable: ^6.10.0

Setup #

  1. Annotate your models with @jsonModel:

Option A: Manual fromJson (No dependencies) #

import 'package:json_factory_annotation/json_factory_annotation.dart';

@JsonModel
class User {
  final int id;
  final String name;
  
  User({required this.id, required this.name});
  
  factory User.fromJson(Map<String, dynamic> json) => User(
    id: json['id'] as int,
    name: json['name'] as String,
  );
  
  Map<String, dynamic> toJson() => {
    'id': id,
    'name': name,
  };
}
import 'package:json_annotation/json_annotation.dart';
import 'package:json_factory_annotation/json_factory_annotation.dart';

part 'user.g.dart';

@JsonModel
@JsonSerializable()
class User {
  final int id;
  final String name;
  
  User({required this.id, required this.name});
  
  factory User.fromJson(Map<String, dynamic> json) => _$UserFromJson(json);
  Map<String, dynamic> toJson() => _$UserToJson(this);
}

Important: Your model class must have a fromJson(Map<String, dynamic>) factory constructor.

  1. Configure build.yaml (optional - for custom output path):
targets:
  $default:
    builders:
      json_factory_generator:jsonFactoryBuilder:
        options:
          output_path: lib/generated  # Default: lib
          output_file_name: json_factory  # Default: json_factory

Generate #

Run the following command to generate the JSON factory code:

dart run build_runner build --delete-conflicting-outputs

This will:

  1. Scan your project for classes annotated with @JsonModel
  2. Generate a centralized json_factory.dart file with type-safe parsing methods
  3. Place the generated file in your configured output directory (default: lib/generated)

Usage #

After generation, you can use the JsonFactory to parse JSON data:

import 'package:your_package/generated/json_factory.dart';

// Parse a single object
final json = {'id': 1, 'name': 'John'};
final user = JsonFactory.fromJson<User>(json);

// Parse a list of objects
final jsonList = [
  {'id': 1, 'name': 'John'},
  {'id': 2, 'name': 'Jane'}
];
final users = JsonFactory.fromJsonList<User>(jsonList);
dart run build_runner build --delete-conflicting-outputs

This will generate:

  • Model .g.dart files (if using json_serializable)
  • lib/generated/json_factory.dart file containing the centralized JsonFactory class

Usage #

import 'package:flutter/material.dart';
import 'generated/json_factory.dart'; // Contains generated JsonFactory

void main() {
  // No initialization needed! 🎉
  runApp(const MyApp());
}

// Parse single objects
final user = JsonFactory.fromJson<User>({"id": 1, "name": "Alice"});

// Parse lists with proper typing
final posts = JsonFactory.fromJson<List<Post>>([
  {"id": 10, "title": "Hello", "content": "Content"},
  {"id": 11, "title": "World", "content": "More content"},
]);

Generic API Response Wrapper #

The library includes a powerful BaseResponse<T> class for handling API responses with generic type support:

import 'package:example/generated/json_factory.dart';
import 'package:json_annotation/json_annotation.dart';

part 'base_response.g.dart';

/// Generic API response wrapper with JsonSerializable
@JsonSerializable(genericArgumentFactories: true)
class BaseResponse<T> {
  final bool success;
  final String message;
  @DataConverter()
  final T? data;
  final int? code;

  BaseResponse({
    required this.success,
    required this.message,
    this.data,
    this.code,
  });

  /// Generated fromJson with generic type support
  factory BaseResponse.fromJson(
    Map<String, dynamic> json,
    T Function(Object? json) fromJsonT,
  ) => _$BaseResponseFromJson(json, fromJsonT);

  /// Generated toJson with generic type support
  Map<String, dynamic> toJson(Object? Function(T value) toJsonT) =>
      _$BaseResponseToJson(this, toJsonT);

  @override
  String toString() {
    return 'BaseResponse(success: $success, message: $message, data: $data, code: $code)';
  }
}

class DataConverter<T> implements JsonConverter<T?, Object?> {
  const DataConverter();

  @override
  T? fromJson(Object? json) {
    return JsonFactory.fromJson(json);
  }

  @override
  Object? toJson(T? object) {
    return object;
  }
}

BaseResponse Usage Examples #

// Example API response for single object
final apiResponse = {
  'success': true,
  'message': 'Data retrieved successfully',
  'code': 200,
  'data': {
    'id': 1,
    'name': 'John Doe'
  }
};

// Parse API response with type safety
final response = BaseResponse<User?>.fromJson(apiResponse, JsonFactory.fromJson);
  
print('API Response:');
print('Success: ${response.success}');
print('Message: ${response.message}');
print('User: ${response.data?.name}');

// Example with list response
final apiListResponse = {
  'success': true,
  'message': 'Posts retrieved successfully',
  'code': 200,
  'data': [
    {'id': 1, 'title': 'Post 1', 'content': 'Content 1'},
    {'id': 2, 'title': 'Post 2', 'content': 'Content 2'},
  ]
};

// Parse API list response with type safety
final listResponse = BaseResponse<List<Post>>.fromJson(apiListResponse, JsonFactory.fromJson);
print('API List Response:');
print('Success: ${listResponse.success}');
print('Message: ${listResponse.message}');
print('Posts:');
listResponse.data?.forEach((post) {
  print('- ${post.title}: ${post.content}');
});

BaseResponse Benefits #

  • Type-safe generic responses - compile-time type checking for API data
  • Consistent API structure - standardized response format across your app
  • Auto JSON conversion - leverages JsonFactory for seamless data parsing
  • Error handling - built-in success/failure status with error codes
  • Flexible data types - supports any type T including primitives, objects, and lists
  • Null safety - proper handling of nullable data fields

## How it works

1. **Annotation scanning**: The generator scans all Dart files for `@jsonModel` classes
2. **Code generation**: Creates a centralized `JsonFactory` class with type-safe factories
3. **Type mapping**: Generates internal maps for efficient type lookup and casting
4. **List handling**: Special logic for parsing `List<T>` with proper generic types
5. **No runtime setup**: Everything is generated at build time, zero initialization needed

## Architecture

Your Models (@jsonModel) ↓ Generator scans files ↓
Generates JsonFactory class ↓ Type-safe fromJson


## Troubleshooting

### Common Issues

- **Target of URI doesn't exist: 'lib/generated/json_factory.dart'**: 
  - Run `dart run build_runner build` first to generate the factory file.
  
- **Factory for type X not found**: 
  - Ensure your class has `@jsonModel` annotation and `fromJson` factory constructor.
  - Check that the class is in a file under `lib/` directory.
  
- **No part file**: 
  - Only needed if using `@JsonSerializable()` - ensure `part 'your_file.g.dart';` exists.
  
- **Build fails**: 
  - Try `dart run build_runner clean` then `dart run build_runner build`.
  
- **Import errors**: 
  - Make sure to import the generated factory file correctly: `import 'generated/json_factory.dart';`
  
- **fromJson not found**: 
  - Ensure your class has `factory ClassName.fromJson(Map<String, dynamic> json)` constructor.

### Build Commands

```bash
# Clean previous builds
dart run build_runner clean

# Generate code
dart run build_runner build

# Generate with conflict resolution
dart run build_runner build --delete-conflicting-outputs

# Watch for changes (development)
dart run build_runner watch

Contributing #

Contributions are welcome! Please feel free to submit a Pull Request.

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add some amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

License #

This project is licensed under the MIT License - see the LICENSE file for details.

Support #

7
likes
130
points
95
downloads

Publisher

unverified uploader

Weekly Downloads

A code generator that creates centralized, type-safe JSON factories for Dart models with automatic discovery and List<T> support.

Repository (GitHub)
View/report issues

Documentation

API reference

License

MIT (license)

Dependencies

analyzer, build, glob, json_factory_annotation, meta, source_gen

More

Packages that depend on json_factory_generator