schema2dart 1.0.0
schema2dart: ^1.0.0 copied to clipboard
Generate strongly typed Dart models from JSON Schema documents.
schema2dart #
Production-ready JSON Schema to Dart code generator with full JSON Schema 2020-12 support.
Generate strongly-typed, immutable Dart models from JSON schemas with runtime validation, security controls, and excellent developer experience.
β¨ Features #
- π§ Build Runner Integration - Automatic code generation during development
- π¦ Standalone API - Programmatic generation for CLI tools and custom builds
- β Full JSON Schema 2020-12 Compliance - All core applicators and keywords
- π‘οΈ Security-First - Offline-by-default with configurable allowlists
- π― Type Safety - Immutable classes with proper null safety
- β‘ Validation Helpers - Optional runtime validation with detailed errors
- π Reference Resolution -
$ref,$anchor,$dynamicAnchorsupport - π Rich Documentation - Schema descriptions become doc comments
- π¨ Extension Annotations - Preserve
x-*custom metadata
π Quick Start #
Using build_runner (Recommended) #
1. Add dependency
# pubspec.yaml
dev_dependencies:
schema2dart: ^latest_version
build_runner: ^2.4.0
2. Configure builder
# build.yaml
targets:
$default:
builders:
schema2dart|schema_builder:
options:
emit_validation_helpers: true
generate_for:
- lib/schemas/**/*.json
3. Add schema
// lib/schemas/person.json
{
"type": "object",
"properties": {
"name": {"type": "string"},
"age": {"type": "integer", "minimum": 0}
},
"required": ["name"]
}
4. Generate
dart run build_runner build --delete-conflicting-outputs
5. Use
import 'package:your_package/schemas/person.dart';
void main() {
final person = Person(name: 'Alice', age: 30);
print(person.toJson());
person.validate(); // Runtime validation
}
Using the API #
import 'package:schema2dart/schema2dart.dart';
void main() {
final schema = {
'type': 'object',
'properties': {
'name': {'type': 'string'},
},
};
final generator = SchemaGenerator(
options: SchemaGeneratorOptions(
rootClassName: 'Person',
emitValidationHelpers: true,
),
);
final code = generator.generate(schema);
print(code); // Generated Dart code
}
π Advanced Features #
Helper Functions #
Generate convenient top-level parse/stringify functions (programmatic API):
final generator = SchemaGenerator(
options: const SchemaGeneratorOptions(
generateHelpers: true,
),
);
// Generated code includes:
Person personFromJson(String str) => Person.fromJson(json.decode(str));
String personToJson(Person data) => json.encode(data.toJson());
// Usage:
final person = personFromJson('{"name": "Alice", "age": 30}');
print(personToJson(person));
Sealed Class Unions (oneOf/anyOf) #
Type-safe union types with exhaustive pattern matching:
{
"oneOf": [
{"type": "string"},
{"type": "integer"},
{"type": "object", "properties": {"id": {"type": "string"}}}
]
}
// Generated sealed class hierarchy:
sealed class Value {}
class ValueString extends Value { final String value; }
class ValueInteger extends Value { final int value; }
class ValueObject extends Value { final String id; }
// Type-safe pattern matching:
String describe(Value v) => switch (v) {
ValueString(value: final s) => 'String: $s',
ValueInteger(value: final i) => 'Int: $i',
ValueObject(id: final id) => 'Object: $id',
};
Reserved Keyword Handling #
Automatically handles Dart reserved words:
{
"properties": {
"class": {"type": "string"},
"const": {"type": "integer"}
}
}
// Generated with safe field names and explicit mapping in toJson/fromJson:
class MyClass {
final String class$;
final int? const$;
const MyClass({
required this.class$,
this.const$,
});
factory MyClass.fromJson(Map<String, dynamic> json) {
final class$ = json['class'] as String;
final const$ = json['const'] as int?;
return MyClass(class$: class$, const$: const$);
}
Map<String, dynamic> toJson() => {
'class': class$,
if (const$ != null) 'const': const$,
};
}
Usage Documentation #
Usage docs are available via the programmatic API (not exposed in the build runner options yet):
final generator = SchemaGenerator(
options: const SchemaGeneratorOptions(
emitUsageDocs: true,
emitReadmeSnippets: true,
),
);
βοΈ Configuration Options #
Build Runner Options #
Build runner currently supports a focused set of options:
| Option | Type | Default | Description |
|---|---|---|---|
root_class |
String | derived | Override the root class name |
prefer_camel_case |
bool | true |
Convert property names to camelCase |
emit_docs |
bool | true |
Emit doc comments from schema metadata |
header |
String | none | Custom file header |
single_file_output |
bool | false |
Emit a single .dart file vs split parts |
emit_validation_helpers |
bool | true |
Generate validate() methods |
enable_format_hints |
bool | false |
Map known format values to richer Dart types |
enable_format_assertions |
bool | false |
Enforce format validation for registry formats |
enable_content_keywords |
bool | false |
Enable contentEncoding/contentMediaType typing |
enable_content_validation |
bool | false |
Validate decoded content against contentSchema |
emit_usage_docs |
bool | false |
Emit usage docs in generated output |
generate_helpers |
bool | false |
Emit top-level JSON helper functions |
emit_readme_snippets |
bool | false |
Emit README snippets in multi-file plans |
allow_network_refs |
bool | false |
Permit network $ref resolution |
network_cache_path |
String | .dart_tool/schema2dart/cache |
Cache directory for fetched refs |
default_dialect |
String | latest |
Dialect URI or none to require explicit $schema |
include_globs |
String or List | **/*.schema.json, **/*.json |
File globs to include |
Example build.yaml:
targets:
$default:
builders:
schema2dart|schema_builder:
options:
emit_validation_helpers: true
default_dialect: "latest"
include_globs:
- lib/schemas/**/*.json
generate_for:
- lib/schemas/**/*.json
include_globs is an additional filter applied inside the builder; generate_for
still controls what build_runner feeds into the builder.
For advanced options (format hints, usage docs, custom loaders, security allowlists), use the programmatic API below.
Programmatic API Options #
SchemaGeneratorOptions(
// Code generation
rootClassName: 'MyClass',
preferCamelCase: true,
emitDocumentation: true,
singleFileOutput: false,
generateHelpers: true,
emitUsageDocs: true,
emitReadmeSnippets: true,
// Validation & types
emitValidationHelpers: true,
enableFormatHints: true,
enableFormatAssertions: false,
enableContentKeywords: false,
enableContentValidation: false,
// Security (see REFERENCE_GOVERNANCE.md)
allowNetworkRefs: false,
allowedNetworkHosts: ['schemas.company.com'],
allowedFilePaths: ['/workspace/schemas'],
maxReferenceDepth: 50,
networkCachePath: '.dart_tool/schema2dart/cache',
defaultDialect: SchemaDialect.latest,
supportedDialects: SchemaDialect.defaultDialectRegistry,
// Custom resolution
documentLoader: customLoader,
onWarning: (msg) => print(msg),
)
π Supported JSON Schema Features #
Core Types β #
- Objects, arrays, strings, numbers, integers, booleans
- Nullable types and optional properties
- Enums with type-safe extensions
- Mixed-type enums - Sealed classes for heterogeneous enum values
- Const values
Validation β #
- String:
minLength,maxLength,pattern,format(assertions opt-in) - Number:
minimum,maximum,multipleOf - Array:
minItems,maxItems,uniqueItems,contains,minContains,maxContains - Object:
required,minProperties,maxProperties,propertyNames
Composition β #
allOf- Type intersectiononeOf- Discriminated unions with sealed classesanyOf- Flexible unions with sealed classesnot- Type negation- Sealed class unions - Type-safe union types with exhaustive pattern matching
Applicators β #
properties,additionalProperties,patternPropertiesitems,prefixItems(2020-12)dependentSchemas,dependentRequiredunevaluatedProperties,unevaluatedItems(2020-12)if/then/elseconditionals
References β #
$ref- Schema references$anchor- Named anchors$dynamicAnchor/$dynamicRef- Dynamic resolution$id- Schema identification- Circular reference detection
Metadata β #
title,descriptionβ Doc commentsdeprecatedβ@Deprecatedannotationdefault,examplesβ Preservedx-*extensions β Custom annotations
Dialects β #
- JSON Schema Draft 2020-12 (full support)
- Draft 2019-09, Draft-07, Draft-06, Draft-04
- Configurable default dialect
Limitations β οΈ #
contentMediaType,contentEncoding,contentSchema- Content decoding supported; contentSchema validation limited to JSON media types- Format hints require
enableFormatHints: true - Format assertions require
enableFormatAssertions: true - Content validation requires
enableContentValidation: true
See LIMITATIONS.md for details and workarounds.
π― Examples #
Check out the example/ directory for:
- build_runner_example - Full build runner setup
- schema2dart_example.dart - Standalone API example
- helper_functions_example.dart - Top-level helpers
- sealed_unions_example.dart -
oneOf/anyOfunions - format_assertions_example.dart -
formatvalidation - content_validation_example.dart -
contentSchemavalidation - reserved_keywords_example.dart - Reserved words
- Real schemas - GitHub workflows, actions, and more
π Security #
schema2dart is secure by default:
- β Offline-by-default - No network access without explicit opt-in
- β Allowlists - Fine-grained control over hosts and file paths
- β Cycle detection - Prevents infinite recursion
- β Depth limits - Configurable maximum reference depth
- β Clear errors - Actionable security messages
See REFERENCE_GOVERNANCE.md for full details.
π Comparison #
| Feature | schema2dart | quicktype | json_serializable |
|---|---|---|---|
| JSON Schema 2020-12 | β Full | β οΈ Partial | β No |
| Build runner | β | β | β |
| Standalone API | β | β | β |
| Runtime validation | β | β | β |
| Security controls | β | β | N/A |
| Circular refs | β | β | β οΈ |
| oneOf/anyOf | β | β | β |
| Documentation | β Excellent | β οΈ Basic | β Good |
π οΈ Development #
Setup #
git clone https://github.com/kingwill101/schema2dart.git
cd schema2dart
dart pub get
Running Tests #
dart test
Code Quality #
dart analyze
dart format .
Building Examples #
cd example/build_runner_example
dart pub get
dart run build_runner build --delete-conflicting-outputs
dart run
π€ Contributing #
Contributions are welcome!