json_annotation_fs 0.1.0+1
json_annotation_fs: ^0.1.0+1 copied to clipboard
Safe JSON annotation package with error handling for Flutter/Dart. Extends json_annotation with robust parsing that prevents crashes on malformed or incomplete JSON data.
Json Annotation FS #
A safe JSON annotation package with error handling for Flutter/Dart. Extends the Dart json_annotation package with robust parsing that prevents crashes on malformed or incomplete JSON data.
Overview #
Json Annotation FS is a Flutter/Dart package that extends the standard json_annotation package with safe JSON parsing capabilities. It prevents application crashes when dealing with incomplete or malformed JSON data by providing intelligent defaults and type coercion.
The Problem #
The standard json_annotation package throws exceptions when:
- A field is missing from the JSON
- The value type doesn't match (e.g., a string instead of a number)
nullis received for a non-nullable field- An array contains elements of incorrect types
This leads to crashes in production.
The Solution #
The package provides safe parsers that:
-
Return default values instead of throwing exceptions:
String→ empty string''int→0double→0.0bool→falseDateTime→DateTime(2000)List<T>→ empty list[]
-
Support nullable fields:
- Return
nullwhen a field is missing or invalid - Require explicit annotations like
@SafeParseStringNullable(), etc.
- Return
-
Perform type conversion:
- Convert string
"123"→ number123 - Convert any value → string via
toString() - Convert string
"true"→ booleantrue
- Convert string
How It Works #
Instead of the standard annotation:
@JsonSerializable() // May crash on bad data
class Person {
final String name;
}
Use:
@JsonSerializableFS() // Safe parsing
class Person {
final String name; // Returns '' if missing
@SafeParseStringNullable()
final String? email; // Returns null if missing
}
Who Is This For #
- FarmSpace projects where APIs may return incomplete data
- Applications working with unstable APIs
- Teams that need resilience to JSON parsing errors
Key Features #
- ✅ Safe defaults - Never crashes, always returns valid values
- ✅ Type coercion - Automatically converts incompatible types
- ✅ Nullable support - Explicit nullable field handling
- ✅ Collection safety - Handles arrays with mixed or missing types
- ✅ Drop-in replacement - Easy migration from
@JsonSerializable() - ✅ Zero configuration - Works out of the box with sensible defaults
Technical Details #
- Extends
JsonSerializablefromjson_annotation - Uses the
JsonConverterpattern for safe parsing - Defaults to renaming fields to
snake_case - Fully compatible with
json_serializableandbuild_runner - Distributed via pub.dev and Azure DevOps Git repository
Bottom line: The package makes JSON parsing resilient to errors, preventing application crashes due to malformed data.
Installation #
From pub.dev (Recommended) #
Install the package and its dependencies:
dart pub add json_annotation_fs json_annotation
dart pub add --dev build_runner json_serializable
Or add to your pubspec.yaml:
dependencies:
json_annotation: ^4.9.0
json_annotation_fs: ^0.1.0
dev_dependencies:
build_runner: ^2.3.3
json_serializable: ^6.8.0
From Git (Alternative) #
If you need to use the Azure DevOps repository instead:
dependencies:
json_annotation: ^4.9.0
json_annotation_fs:
git:
# repository URL. Azure login required
url: https://AfricaFarmersNetwork-DevOps@dev.azure.com/AfricaFarmersNetwork-DevOps/Json_annotation_package-flutter/_git/Json_annotation_package-flutter
# desired repository branch
ref: main
dev_dependencies:
build_runner: ^2.3.3
json_serializable: ^6.8.0
Usage #
Basic Usage #
Annotate your class with @JsonSerializableFS() instead of @JsonSerializable(). All properties and methods behave the same, but with built-in parsing safety.
The default fieldRename property is set to FieldRename.snake, so your JSON fields will automatically be converted from snake_case to camelCase in Dart.
Available Annotations #
For Nullable Primitive Types
All nullable primitive fields must be annotated with the corresponding safe parser:
| Type | Annotation |
|---|---|
String? |
@SafeParseStringNullable() |
int? |
@SafeParseIntNullable() |
double? |
@SafeParseDoubleNullable() |
bool? |
@SafeParseBoolNullable() |
DateTime? |
@SafeParseDateTimeNullable() |
For Nullable Collections
All nullable list fields must be annotated:
| Type | Annotation |
|---|---|
List<String>? |
@SafeParseStringListNullable() |
List<int>? |
@SafeParseIntListNullable() |
List<double>? |
@SafeParseDoubleListNullable() |
List<bool>? |
@SafeParseBoolListNullable() |
For Custom Object Lists
All non-nullable lists of custom objects must have a default value:
@JsonKey(defaultValue: [])
final List<Person> family;
Nullable lists of custom objects work without annotation:
final List<Person>? friends; // No annotation needed
Migration from json_annotation #
To migrate from @JsonSerializable() to @JsonSerializableFS():
- Replace
@JsonSerializable()with@JsonSerializableFS() - Add nullable annotations to nullable fields (see table above)
- Add
@JsonKey(defaultValue: [])to non-nullable custom object lists - Run
dart run build_runner build --delete-conflicting-outputs
That's it! Your code will now handle malformed JSON gracefully.
Example #
Complete Example #
Here's a complete example showing all features of the package:
import 'package:json_annotation_fs/json_annotation_fs.dart';
part 'person_model.g.dart';
@JsonSerializableFS()
class Person {
Person({
required this.firstName,
this.lastName,
required this.age,
this.email,
required this.childrenNames,
this.petNames,
required this.family,
this.friends,
});
// Non-nullable fields: return defaults if missing
final String firstName; // Returns '' if missing
final int age; // Returns 0 if missing
final List<String> childrenNames; // Returns [] if missing
// Nullable fields: must be annotated, return null if missing
@SafeParseStringNullable()
final String? lastName; // Returns null if missing
@SafeParseStringNullable()
final String? email; // Returns null if missing
@SafeParseStringListNullable()
final List<String>? petNames; // Returns null if missing
// Custom object lists: non-nullable requires default
@JsonKey(defaultValue: [])
final List<Person> family; // Returns [] if missing
// Nullable custom object lists: no annotation needed
final List<Person>? friends; // Returns null if missing
factory Person.fromJson(Map<String, dynamic> json) => _$PersonFromJson(json);
Map<String, dynamic> toJson() => _$PersonToJson(this);
}
Handling Malformed JSON #
The package gracefully handles various JSON issues:
// JSON with missing fields and wrong types
final json = {
'first_name': 'John',
// 'age' is missing
'email': 12345, // Wrong type (number instead of string)
'children_names': ['Alice', 'Bob'],
// 'pet_names' is missing
};
final person = Person.fromJson(json);
print(person.firstName); // 'John' (from JSON)
print(person.age); // 0 (default, field was missing)
print(person.email); // '12345' (converted from number to string)
print(person.childrenNames); // ['Alice', 'Bob'] (from JSON)
print(person.petNames); // null (missing, nullable field)
Code Generation #
After writing your model, generate the serialization code:
dart run build_runner build --delete-conflicting-outputs
For continuous development, use watch mode:
dart run build_runner watch --delete-conflicting-outputs
Additional Resources #
License #
This package is licensed under the MIT License. See the LICENSE file for details.
Related Packages #
- json_annotation - Base annotation package
- json_serializable - Code generator for JSON serialization
- build_runner - Build system for Dart code generation