dart_json_mapper 1.4.4

Build Status pub package Build Status

This package allows programmers to annotate Dart classes in order to Serialize / Deserialize them to / from JSON.

Why? #

  • Compatible with all Dart platforms, including Flutter and Web platforms
  • No need to extend your classes from any mixins/base/abstract classes to keep code leaner
  • Clean and simple setup, transparent and straight-forward usage with no heavy maintenance
  • No extra boilerplate, 100% generated code, which you'll never see.
  • Custom converters per each class field, full control over the process
  • NO dependency on dart:mirrors, one of the reasons is described here.
  • Because Serialization/Deserialization is NOT a responsibility of your Model classes.

Dart classes reflection mechanism is based on reflectable library. This means "extended types information" is auto-generated out of existing Dart program guided by the annotated classes only, as the result types information is accessible at runtime, at a reduced cost.

Typical Flutter.io project integration sample can be found here

Basic setup #

Please add the following dependencies to your pubspec.yaml:

  dart_json_mapper: any
  build_runner: any

Say, you have a dart program main.dart having some classes intended to be traveling to JSON and back.

  • First thing you should do is to put @jsonSerializable annotation on each of those classes
  • Next step is to auto generate main.reflectable.dart file. And afterwards import that file into main.dart


import 'package:dart_json_mapper/dart_json_mapper.dart';

import 'main.reflectable.dart'; // Import generated code.

@jsonSerializable // This annotation let instances of MyData traveling to/from JSON
class MyData {
  int a = 123;

  @JsonProperty(ignore: true)
  bool b;

  @JsonProperty(name: 'd')
  String c;

  MyData(this.a, this.b, this.c);

main() {
  initializeReflectable(); // Imported from main.reflectable.dart
  print(JsonMapper.serialize(MyData(456, true, "yes")));


  "a": 456,
  "d": "yes"

Go ahead and create a build.yaml file in your project root directory. Then add the following content:

          - lib/main.dart
          formatted: true

Now run the code generation step with the root of your package as the current directory:

> pub run build_runner build

You'll need to re-run code generation each time you are making changes to lib/main.dart So for development time, use watch like this

> pub run build_runner watch

Each time you modify your project code, all *.reflectable.dart files will be updated as well.

  • Next step is to add "*.reflectable.dart" to your .gitignore
  • And this is it, you are all set and ready to go. Happy coding!

Format DateTime / num types #

In order to format DateTime or num instance as a JSON string, it is possible to provide intl based formatting patterns.


@JsonProperty(converterParams: {'format': 'MM-dd-yyyy H:m:s'})
DateTime lastPromotionDate = DateTime(2008, 05, 13, 22, 33, 44);

@JsonProperty(converterParams: {'format': 'MM/dd/yyyy'})
DateTime hireDate = DateTime(2003, 02, 28);


"lastPromotionDate": "05-13-2008 22:33:44",
"hireDate": "02/28/2003"


@JsonProperty(converterParams: {'format': '##.##'})
num salary = 1200000.246;


"salary": "1200000.25"

As well, it is possible to utilize converterParams map to provide custom parameters to your custom converters.

Example with immutable class #

enum Color { Red, Blue, Green, Brown, Yellow, Black, White }

class Car {
    @JsonProperty(name: 'modelName')
    String model;
    @JsonProperty(enumValues: Color.values)
    Color color;
    @JsonProperty(ignore: true)
    Car replacement;
    Car(this.model, this.color);

class Immutable {
    final int id;
    final String name;
    final Car car;
    const Immutable(this.id, this.name, this.car);

    Immutable(1, 'Bob', Car('Audi', Color.Green))


 "id": 1,
 "name": "Bob",
 "car": {
  "modelName": "Audi",
  "color": "Color.Green"

Constructor parameters #

Sometimes you don't really care or don't want to store some json property as a dedicated class field, but instead, you would like to use it's value in constructor to calculate other class properties. This way you don't have a convenience to annotate a class field, but you could utilize constructor parameter for that.

With the input JSON like this:


You could potentially have a class like this:

class BusinessObject {
  final bool logisticsChecked;
  final bool logisticsOK;

      : logisticsChecked = false,
        logisticsOK = true;

      @JsonProperty(name: 'LogistikTeileInOrdnung') String processed)
      : logisticsChecked = processed != null && processed != 'null',
        logisticsOK = processed == 'true';

Unmapped properties #

If you are looking for an alternative to Java Jackson @JsonAnySetter / @JsonAnyGetter It is possible to configure the same scenario as follows:

class UnmappedProperties {
  String name;

  Map<String, dynamic> _extraPropsMap = {};

  void unmappedSet(String name, dynamic value) {
    _extraPropsMap[name] = value;

  Map<String, dynamic> unmappedGet() {
    return _extraPropsMap;

// given
final json = '''{"name":"Bob","extra1":1,"extra2":"xxx"}''';

// when
final instance = JsonMapper.deserialize<UnmappedProperties>(json);

// then
expect(instance.name, 'Bob');
expect(instance._extraPropsMap['name'], null);
expect(instance._extraPropsMap['extra1'], 1);
expect(instance._extraPropsMap['extra2'], 'xxx');

Iterable types #

Since Dart language has no possibility to create typed iterables dynamically, it's a bit of a challenge to create exact typed lists/sets/etc via reflection approach. Those types has to be declared explicitly.

For example List() will produce List<dynamic> type which can't be directly set to the concrete target field List<Car> for instance. So obvious workaround will be to cast List<dynamic> => List<Car>, which can be performed as List<dynamic>().cast<Car>().

In order to do so, we'll use Value Decorator Function inspired by Decorator pattern.

final iterableCarDecorator = (value) => value.cast<Car>();
final String json = '[{"modelName": "Audi", "color": "Color.Green"}]';

List<Car> myCarsList = JsonMapper.deserialize(json);
Set<Car> myCarsSet = JsonMapper.deserialize(json);

Basic iterable based generics using Dart built-in types like List<num>, List<Sring>, List<bool>, List<DateTime>, Set<num>, Set<Sring>, Set<bool>, Set<DateTime>, etc. supported out of the box.

For custom iterable types like List<Car> / Set<Car> you have to register value decorator function as showed in a code snippet above before using deserialization. This function will have explicit cast to concrete iterable type.

List of Lists of Lists ... #

Using value decorators, it's possible to configure nested lists of virtually any depth.

class Item {}

class ListOfLists {
  List<List<Item>> lists;

// given
final json = '''{
 "lists": [
   [{}, {}],
   [{}, {}, {}]

// when
JsonMapper.registerValueDecorator<List<List<Item>>>((value) => value.cast<List<Item>>());
JsonMapper.registerValueDecorator<List<Item>>((value) => value.cast<Item>());
final target = JsonMapper.deserialize<ListOfLists>(json);
// then
expect(target.lists.length, 2);
expect(target.lists.first.length, 2);
expect(target.lists.last.length, 3);
expect(target.lists.first.first, TypeMatcher<Item>());
expect(target.lists.last.first, TypeMatcher<Item>());

Enum types #

Enum construction in Dart has a specific meaning, and has to be treated accordingly.

Enum declarations should not be annotated with @jsonSerializable, since they are not a classes technically, but a special built in types.

enum Color { Red, Blue, Green, Brown, Yellow, Black, White }
@JsonProperty(enumValues: Color.values)
Color color;

Each enum based class field has to be annotated as showed in a snippet above. Enum.values refers to a list of all possible enum values, it's a handy built in capability of all enum based types. Without providing all values it's not possible to traverse it's values properly.

Inherited classes derived from abstract / base class #

Please use complementary @Json(typeNameProperty: 'typeName') annotation for subclasses derived from abstract or base class. This way dart-json-mapper will dump the concrete object type to the JSON output during serialization process. This ensures, that dart-json-mapper will be able to reconstruct the object with the proper type during deserialization process.

@Json(typeNameProperty: 'typeName')
abstract class Business {
  String name;

class Hotel extends Business {
  int stars;


class Startup extends Business {
  int userCount;


class Stakeholder {
  String fullName;
  List<Business> businesses;

  Stakeholder(this.fullName, this.businesses);

// given
final jack = Stakeholder("Jack", [Startup(10), Hotel(4)]);

// when
JsonMapper.registerValueDecorator<List<Business>>((value) => value.cast<Business>());
final String json = JsonMapper.serialize(jack);
final Stakeholder target = JsonMapper.deserialize(json);

// then
expect(target.businesses[0], TypeMatcher<Startup>());
expect(target.businesses[1], TypeMatcher<Hotel>());

Name casing styles [Pascal, Kebab, Snake, SnakeAllCaps]

Assuming your Dart code is following Camel case style, but that is not always true for JSON models, they could follow one of those popular - Pascal, Kebab, Snake, SnakeAllCaps styles, right?

That's why we need a way to manage that in an organized way, instead of hand coding each property using @JsonProperty(name: ...) it is possible to pass CaseStyle parameter to serialization / deserialization methods.

class NameCaseObject {
  String mainTitle;
  String description;
  bool hasMainProperty;

  NameCaseObject({this.mainTitle, this.description, this.hasMainProperty});

/// Serialization

// given
final instance = NameCaseObject(
    mainTitle: 'title', description: 'desc', hasMainProperty: true);
// when
final json = JsonMapper.serialize(instance,
    SerializationOptions(indent: '', caseStyle: CaseStyle.Kebab));
// then
expect(json, '''{"main-title":"title","description":"desc","has-main-property":true}''');

/// Deserialization

// given
final json = '''{"main-title":"title","description":"desc","has-main-property":true}''';
// when
final instance = JsonMapper.deserialize<NameCaseObject>(
    json, DeserializationOptions(caseStyle: CaseStyle.Kebab));
// then
expect(instance.mainTitle, 'title');
expect(instance.description, 'desc');
expect(instance.hasMainProperty, true);

Nesting configuration #

In case if you need to operate on particular portions of huge JSON object and you don't have a true desire to reconstruct the same deep nested JSON objects hierarchy with corresponding Dart classes. This section is for you!

Say, you have a json similar to this one

  "root": {
    "foo": {
      "bar": {
        "baz": {
          "items": [

And with code similar to this one

@Json(name: 'root/foo/bar')
class RootObject {
  @JsonProperty(name: 'baz/items')
  List<String> items;


// when
final RootObject instance = JsonMapper.deserialize(json);
// then
expect(instance.items.length, 3);
expect(instance.items, ['a', 'b', 'c']);

you'll have it done nice and quick.

@Json(name: 'root/foo/bar') provides a root nesting for the entire annotated class, this means all class fields will be nested under this 'root/foo/bar' path in Json.

@JsonProperty(name: 'baz/items') provides a field nesting relative to the class root nesting

name is compliant with RFC 6901 JSON pointer

Schemes #

Scheme - is a set of annotations associated with common scheme id. This enables the possibility to map a single Dart class to many different JSON structures.

This approach usually useful for distinguishing [DEV, PROD, TEST, ...] environments, w/o producing separate Dart classes for each environment.

enum Scheme { A, B }

@Json(name: 'default')
@Json(name: '_', scheme: Scheme.B)
@Json(name: 'root', scheme: Scheme.A)
class Object {
  @JsonProperty(name: 'title_test', scheme: Scheme.B)
  String title;


// given
final instance = Object('Scheme A');
// when
final json = JsonMapper.serialize(instance, SerializationOptions(indent: '', scheme: Scheme.A));
// then
expect(json, '''{"root":{"title":"Scheme A"}}''');

// given
final instance = Object('Scheme B');
// when
final json = JsonMapper.serialize(instance, SerializationOptions(indent: '', scheme: Scheme.B));
// then
expect(json, '''{"_":{"title_test":"Scheme B"}}''');

// given
final instance = Object('No Scheme');
// when
final json = JsonMapper.serialize(instance, SerializationOptions(indent: ''));
// then
expect(json, '''{"default":{"title":"No Scheme"}}''');

Custom types #

For the very custom types, specific ones, or doesn't currently supported by this library, you can provide your own custom Converter class per each custom runtimeType.

/// Abstract class for custom converters implementations
abstract class ICustomConverter<T> {
  dynamic toJSON(T object, [JsonProperty jsonProperty]);
  T fromJSON(dynamic jsonValue, [JsonProperty jsonProperty]);

All you need to get going with this, is to implement this abstract class

class CustomStringConverter implements ICustomConverter<String> {
  const CustomStringConverter() : super();

  String fromJSON(dynamic jsonValue, [JsonProperty jsonProperty]) {
    return jsonValue;

  dynamic toJSON(String object, [JsonProperty jsonProperty]) {
    return '_${object}_';

And register it afterwards, if you want to have it applied for all occurrences of specified type


OR use it individually on selected class fields, via @JsonProperty annotation

@JsonProperty(converter: CustomStringConverter())
String title;

Annotations #

  • @JsonSerializable() or @jsonSerializable for short, It's a required class only marker annotation. Use it to mark all the Dart classes you'd like to be traveling to / from JSON
    • Has NO params
  • @JsonConstructor() or @jsonConstructor for short, It's an optional constructor only marker annotation. Use it to mark specific Dart class constructor you'd like to be used during deserialization.
    • scheme dynamic Scheme marker to associate this meta information with particular mapping scheme
  • @Json(...) It's an optional class only annotation, describes a Dart class to JSON Object mapping. Why it's not a @JsonObject()? just for you to type less characters 😄
    • name Defines RFC 6901 JSON pointer, denotes the json Object root name/path to be used for mapping. Example: 'foo', 'bar', 'foo/bar/baz'
    • typeNameProperty declares the necessity for annotated class and all it's subclasses to dump their own type name to the property named as this param value
    • ignoreNullMembers If set to true Null class members will be excluded from serialization process
    • allowCircularReferences As of int type. Allows certain number of circular object references during serialization.
    • scheme dynamic Scheme marker to associate this meta information with particular mapping scheme
  • @JsonProperty(...) It's an optional class member annotation, describes JSON Object property mapping.
    • name Defines RFC 6901 JSON pointer, denotes the name/path to be used for property mapping relative to the class root nesting Example: 'foo', 'bar', 'foo/bar/baz'
    • scheme dynamic Scheme marker to associate this meta information with particular mapping scheme
    • converter Declares custom converter instance, to be used for annotated field serialization / deserialization
    • converterParams A Map<String, dynamic> of named parameters to be passed to the converter instance
    • ignore A bool declares annotated field as ignored so it will be excluded from serialization / deserialization process
    • ignoreIfNull A bool declares annotated field as ignored if it's value is null so it will be excluded from serialization / deserialization process
    • enumValues Provides a way to specify enum values, via Dart built in capability for all Enum instances. Enum.values
    • defaultValue Defines field default value

Complementary adapter libraries #

If you want a seamless integration with popular use cases, feel free to pick an existing adapter or create one for your use case and make a PR to this repo.

Adapter - is a library which contains a bundle of pre-configured:

For example, you would like to use Int32 type provided by Fixnum library in your app.

  • Make sure you have following dependencies in your pubspec.yaml:

        fixnum: any
        dart_json_mapper: any
        dart_json_mapper_fixnum: any
        build_runner: any
  • Usually, adapter library contains a single global function to invoke in your main.dart, so

      import 'package:fixnum/fixnum.dart' show Int32;
      import 'package:dart_json_mapper/dart_json_mapper.dart';
      import 'package:dart_json_mapper_fixnum/dart_json_mapper_fixnum.dart';
      import 'main.reflectable.dart'; // Import generated code.
      class FixnumExample {
        Int32 integer32;
      main() {
        initializeReflectable(); // Imported from main.reflectable.dart
        initializeJsonMapperForFixnum(); // Imported from dart_json_mapper_fixnum


        "integer32": 1234567890

1.4.4 #

  • #33, Provide default values for @JsonProperty(defaultValue: ...)
  • #35, SerializationOptions enriched with global ignoreNullMembers flag

1.4.3 #

  • #32, Collect Unmapped Properties implemented

1.4.2 #

  • #30, Support for RFC 6901 JSON pointer for mapping names/paths

1.4.1 #

  • #29, List of Lists use case covered.

1.4.0 #

  • Enhancement #21 implemented, support @JsonConstructor to pick appropriate constructor for deserialization.
  • Enhancement #23 implemented, support for field names casing options for serialization. [Pascal, Kebab, Snake, SnakeAllCaps]

1.3.5 #

  • fix for #28
  • Enhancement #22 implemented, support @JsonProperty annotation on constructor params when there is no associated field.

1.3.4 #

  • Bump reflectable dependency to the latest stable

1.3.3 #

  • Fix issue #26

1.3.2 #

  • Fix special A/B inception case for #25

1.3.1 #

  • Imports refactored, from now on everything is imported from a single import 'package:dart_json_mapper/dart_json_mapper.dart'; instead of several imports

1.2.10 #

  • Optional template parameter added to SerializationOptions. Allows to render JSON on top of existing template map object.

1.2.9 #

  • Introduced possibility to specify number of allowed circular references @Json(allowCircularReferences: 1)

1.2.8 #

  • Schemes introduced. Scheme - is a set of meta annotations associated with common scheme id. This enables the possibility to map single Dart class to many JSON structures.

1.2.7 #

  • adopt pedantic for code style lints

1.2.6 #

  • Introduced deep nesting for property names

1.2.5 #

  • Introduced clone util method. Clone Dart objects made simple!
  • Introduced support for public getters-only serialization

1.2.4 #

  • fix converter resolution logic

1.2.3 #

  • Fixnum support extracted as a standalone adapter library

1.2.2 #

  • proper fix for issue #20, support for complementary "adapter" libraries added

1.2.1 #

  • fix for issue #20

1.2.0 #

  • Improved configuration for class hierarchies processing. [breaking change]
  • fix for issues #19, #18

1.1.12 #

  • A convenience toJson/fromJson methods introduced

1.1.11 #

  • fix lint errors, update dependencies

1.1.10 #

  • fix for issue #15

1.1.9 #

  • proper fix for issue #9
  • refactoring

1.1.8 #

  • @JsonProperty.ignoreIfNull introduced, to skip null properties from processing

1.1.7 #

  • Issues #10, #11 has been fixed

1.1.6 #

  • Issue #9 has been fixed

1.1.5 #

  • Map<String, dynamic> easing methods toMap/fromMap introduced.

1.1.4 #

  • Issue #8 has been fixed

1.1.3 #

  • Documented use case with Inherited classes derived from abstract / base class

1.1.2 #

  • Issues #5, #6 has been fixed

1.1.1 #

  • Issue #4 has been fixed

1.1.0 #

  • Update build process, from now on relying on build_runner configured over build.yaml
  • Issues #2, #3 has been fixed

1.0.9 #

  • Added support for derived classes

1.0.8 #

  • Fixnum types Int32, Int64 support added

1.0.7 #

  • Iterable based types support enhanced

1.0.6 #

  • Set based types support added

1.0.5 #

  • Uint8List, BigInt types support added

1.0.4 #

  • Value decorators support enhanced

1.0.3 #

  • Value decorator introduced

1.0.2 #

  • Added some docs
  • Added test on ignored class field

1.0.1 #

  • Improved Support for Map<K, V> type
  • Added basic Support for dynamic type

1.0.0 #

  • Positional constructor parameters support
  • Support for Symbol, Map types
  • More tests added

0.1.3 #

  • Support Dart 2.0
  • Support latest reflectable library changes
  • Remove dependency on barback

0.1.2 #

  • Converters registry introduced
  • Error handling improved

0.1.1 #

  • Converter auto detection based on field type
  • Update pubspec for Dart 2.0

0.1.0 #

  • Update readme
  • Immutable classes serialization / deserialization support

0.0.9 #

  • Tiny update to fix pubspec & readme

0.0.8 #

  • Circular reference detection during serialization added

0.0.7 #

  • Support Lists of Enums, Dates, Numbers etc.
  • @JsonSerializable() => @jsonSerializable

0.0.6 #

  • build & watch scripts added as a tooling for development time

0.0.5 #

  • DateConverter & NumberConverter introduced
  • Parameters for custom converter introduced

0.0.4 #

  • Convert Enum values to string by default, to skip a disordered values drawback with indexed enum values.
  • Enum's does not have to be annotated, since almost all of them are parts of third party libraries w/o access for modification.
  • dateTimeConverter introduced

0.0.2 #

  • Remove dependency on dart:mirrors.

0.0.0 #

  • First published release.


import 'package:dart_json_mapper/dart_json_mapper.dart';

import 'example.reflectable.dart'; // Import generated code.

enum Color { Red, Blue, Green, Brown, Yellow, Black, White }

class Car {
  @JsonProperty(name: 'modelName')
  String model;

  @JsonProperty(enumValues: Color.values)
  Color color;

  Car(this.model, this.color);

  String toString() {
    return 'Car{model: $model, color: $color}';

class Person {
  List<String> skills = ['Go', 'Dart', 'Flutter'];

  @JsonProperty(name: 'last_promotion_date', ignore: true)
  DateTime lastPromotionDate;

  @JsonProperty(name: 'hire_date')
  DateTime hireDate = DateTime(2003, 02, 28);

  bool married = true;
  String name = 'Forest';

  @JsonProperty(ignore: true)
  num salary;

  num dob;
  num age = 36;
  var lastName = 'Gump';

  @JsonProperty(name: 'eye_color', enumValues: Color.values)
  Color eyeColor = Color.Blue;

  @JsonProperty(enumValues: Color.values, converter: enumConverterNumeric)
  Color hairColor = Color.Brown;

  List<Car> vehicles = [Car('Tesla', Color.Black), Car('BMW', Color.Red)];

  String get fullName => '${name} ${lastName}';


  String toString() {
    return 'Person{skills: $skills, lastPromotionDate: '
        '$lastPromotionDate, hireDate: $hireDate, married: $married, name: '
        '$name, salary: $salary, dob: $dob, age: $age, lastName: $lastName, '
        'eyeColor: $eyeColor, hairColor: $hairColor, vehicles: $vehicles}';

void main() {

  final personJson = '''{
 "skills": [
 "hire_date": "2003-02-28",
 "married": true,
 "name": "Forest",
 "dob": null,
 "age": 36,
 "lastName": "Gump",
 "eye_color": "Color.Blue",
 "hairColor": 3,
 "vehicles": [
   "modelName": "Tesla",
   "color": "Color.Black"
   "modelName": "BMW",
   "color": "Color.Red"

  // Because Person has a custom list List<Car>, we have to provide value cast decorator for it
  // to be able to Deserialize
  final iterableCarDecorator = (value) => value.cast<Car>();

  // Serialize

  // Deserialize

Use this package as a library

1. Depend on it

Add this to your package's pubspec.yaml file:

  dart_json_mapper: ^1.4.4

2. Install it

You can install packages from the command line:

with pub:

$ pub get

with Flutter:

$ flutter pub get

Alternatively, your editor might support pub get or flutter pub get. Check the docs for your editor to learn more.

3. Import it

Now in your Dart code, you can use:

import 'package:dart_json_mapper/dart_json_mapper.dart';
Describes how popular the package is relative to other packages. [more]
Code health derived from static analysis. [more]
Reflects how tidy and up-to-date the package is. [more]
Weighted score of the above. [more]
Learn more about scoring.

We analyzed this package on Feb 15, 2020, and provided a score, details, and suggestions below. Analysis was completed with status completed using:

  • Dart: 2.7.1
  • pana: 0.13.5


Package Constraint Resolved Available
Direct dependencies
Dart SDK >=2.6.1 <3.0.0
intl ^0.16.1 0.16.1
reflectable ^2.2.1+2 2.2.1+2
Transitive dependencies
_fe_analyzer_shared 1.0.3
analyzer 0.39.4
args 1.5.2
async 2.4.0
build 1.2.2
build_config 0.4.2
build_daemon 2.1.3
build_resolvers 1.3.3
build_runner_core 4.4.0
built_collection 4.3.2
built_value 7.0.9
charcode 1.1.3
checked_yaml 1.0.2
code_builder 3.2.1
collection 1.14.12
convert 2.1.1
crypto 2.1.4
csslib 0.16.1
dart_style 1.3.3
fixnum 0.10.11
glob 1.2.0
graphs 0.2.0
html 0.14.0+3
http 0.12.0+4
http_multi_server 2.2.0
http_parser 3.1.3
io 0.3.3
js 0.6.1+1
json_annotation 3.0.1
logging 0.11.4
matcher 0.12.6
meta 1.1.8
mime 0.9.6+3
node_interop 1.0.3
node_io 1.0.1+2
package_config 1.1.0 2.0.0
package_resolver 1.0.10
path 1.6.4
pool 1.4.0
pub_semver 1.4.3
pubspec_parse 0.1.5
quiver 2.1.2+1
shelf 0.7.5
shelf_web_socket 0.2.3
source_span 1.6.0
stack_trace 1.9.3
stream_channel 2.0.0
stream_transform 1.1.0
string_scanner 1.0.5
term_glyph 1.1.0
timing 0.1.1+2
typed_data 1.1.6
watcher 0.9.7+13
web_socket_channel 1.1.0
yaml 2.2.0
Dev dependencies
build_runner any 1.7.4
build_test any
pedantic ^1.9.0 1.9.0
test any