dynamo 0.1.0

  • README.md
  • Example
  • Installing
  • Versions
  • 0

dynamo #

A JSON serialization for object graphs. This library will not generate a simple JSON but add some information for types and references. Thus this library supports circle references, inheritance and object graphs (reference aware).

Dynamo uses source_gen to generate code, and has no dependency to the 'dart:mirror' at all.

Dynamo is rewritten from scratch, but influenced from Dartson (dartson on github), with some some extensions to Dartson.

Alternatives #

If you need just simple JSON serialization you might use JsonSerializable from source_gen instead, or Dartson. Latter uses code transformers.

Annotations #

Serializable Objects must be annotated with @DynamoSerializable(), and also must use a generated mixin (Namepattern is _$classnameDynamoMixin) Fields with missing getter or setter will be ignored. Optional fields can be annotated with @DynamoEntry() in order to use a different json key, or be ignored for serialization.

class Member extends Object with _$MemberDynamoMixin {

  int id = 0;

  String firstName;

  @DynamoEntry(name: 'last_name')
  String lastName;

  DateTime registered;

  @DynamoEntry(ignore: true)
  bool ignoreMe;

  Member.withIdAndName(this.id, this.firstName, this.lastName) {}

  // will be ignored (no setter)
  bool get isNew => id < 1;


Generate Mixins #

Build steps are needed to setup. See the source_gen > Running Generators and example.

Serialization #

The root object for serialization (toJson) or deserialization (fromJson) might be:

  • a list,
  • a map,
  • a simple type (bool, num, String),
  • or a registered type (annotated with DynamoSerializable and using a generated DynamoMixin).

The protocol for serialization is:

  String toJson(dynamic value);
  dynamic fromJson(String json, {InstanceFactory factory});

Usually fromJson will detect the target instance but optional a factory can be passed instead.

type registration #

Since no mirroring system will be used, each type must be registered using registerType with an identifier, the type and a factory for new instances:

  new Dynamo()
    ..registerType('member', Member, () => new Member())

dynamo configuration #

Different dynamo configurations might be used (with the same serializable objects) to produce different JSON output.

  var dynamo1 = new Dynamo()
    ..addTransformer(new MemberTypeTransformer())
    ..registerType('member', Member, () => new Member())
    ..registerType('tag', Tag, () => new Tag())

  var dynamo2 = new Dynamo()
    ..registerType('member', Member, () => new Member())
    ..registerType('tag', Tag, () => new Tag())
    ..addTransformer(new MemberTransformer(allMembers))

transformers #

A type transformer can be added to a dynamo (configuration) e.g for mapping enum values, or just a representation for an entity.

Transformer sample: Enum mapping #
enum MemberType { adult, student, unemployed, pensioner, child, vip }

class Member extends Object with _$MemberDynamoMixin {

  MemberType type;



class MemberTypeTransformer extends TypeTransformer<MemberType> {
  final String KEY = 'membertype';
  final MemberType defaultMemberType = MemberType.adult;

  Map<String,MemberType> typeMap = const {
    'adult': MemberType.adult,
    'student': MemberType.student,
    'unemployed': MemberType.unemployed,
    'pensioner': MemberType.pensioner,
    'child': MemberType.child,
    'vip': MemberType.vip

  bool canDecode(value) => value is MemberType;

  bool canEncode(value) => value is Map && value.containsKey(KEY);

  dynamic encode(MemberType value) {
    var type = value == null ? defaultMemberType : value;
    for (var key in typeMap.keys) {
      if (typeMap[key] == type) {
        return {KEY : key};
    throw new ArgumentError("unsupported type");

  MemberType decode(dynamic value) => typeMap.containsKey(value[KEY]) ? typeMap[value[KEY]] : defaultMemberType;


main() {
  var dynamo = new Dynamo()
      ..addTransformer(new MemberTypeTransformer())
      ..registerType('member', Member, () => new Member());
  // dynamo.toJson(member);
  // dynamo.fromJson(member);
Transformer sample: Representation instead of whole mapped instance #

E.g. if instances already known then only a representation (e.g. ID of an entity) can be serialized instead:

    class MemberTransformer implements TypeTransformer<Member> {
      static const String KEY = 'memberId';
      final List<Member> members; // usually a repository
      bool canEncode(value) => value is Member;
      encode(Member value) => {KEY: value.id};
      bool canDecode(value) => value is Map && value.containsKey(KEY);
      Member decode(value) => members.firstWhere((member) => member.id == value[KEY], orElse: () => null);

    // usually repositories for members
    List<Member> members = [m1, m2, m3];

    MemberTransformer memberTransformer = new MemberTransformer(members);

    Dynamo dynamo = new Dynamo()

    var output = dynamo.toJson(m2);

will produce:


datetime transformer #

DateTime will be serialized automatically for fields but due to JSON restriction, can not be automatically detected if part of an untyped list oder map (only by guessing). If DateTime is used in untyped collections the bundled DateTimeTransformer can be used:

    Dynamo dynamo = new Dynamo()
      ..addTransformer(new DateTimeTransformer("_dt_"))

for values e.g. List values = [new DateTime.utc(2017,1,29), new DateTime.utc(2017,1,28)];

dynamo will produce


But now, also fields in registered type will use this transformer for DateTime fields:


instead of (using internal datetime transformers for fields):


generate pretty json output #

class PrettyJsonCodec extends JsonCodec {
  JsonEncoder get encoder {
    return const JsonEncoder.withIndent('  ');

new Dynamo(codec: new PrettyJsonCodec()) ....

customize json keys for type and reference information #

default keys:

  • typeKey: _isa_ (used to identify the type)
  • instanceIdKey: _id#_ (used to add a sequential number)
  • referenceKey: _ref_ (used to reference to a prior serialized instance)

Sample: serialize same instance (of type member) twice in a list:


To customize these key use following setters:

    Dynamo dynamo = createCommonDynamo(JSON)
      ..typeKey = r"$typeof"
      ..instanceIdKey = r"$instance"
      ..referenceKey = r"$reference";

Same example will produce:


Example #

See example of dynamo in Github Repo.

Not yet implemented #

  • using different name for imported dynamo library (import as)

Changelog #

0.1.0 2017-01-20 #

  • docu added, example improved

0.0.4 2017-01-19 #

  • example added

0.0.3 2017-01-18 #

  • fixes field annotation handling

0.0.2 2017-01-17 #

  • added strong mode support
  • using abstract accessors in mixin class

0.0.1 2017-01-15 #

  • Initial working draft


library dynamo_example;

import 'dart:convert';

import 'package:dynamo/dynamo.dart';

part 'dynamo_example.g.dart'; // generated

part 'model/domain/member.dart';
part 'model/domain/tag.dart';

part 'model/transformer/member_type_transformer.dart';

part 'model/message/base.dart';
part 'model/message/queries.dart';

final defaultDynamo = createCommonDynamo(JSON);
final defaultTransactionDynamo = createTransactionDynamo(JSON);
final prettyDynamo = createCommonDynamo(new PrettyJsonCodec());

class PrettyJsonCodec extends JsonCodec {
  JsonEncoder get encoder {
    return const JsonEncoder.withIndent('  ');

Dynamo createCommonDynamo(JsonCodec json) {
  return new Dynamo(codec: json)
    ..addTransformer(new MemberTypeTransformer())
    ..registerType('member', Member, () => new Member())
    ..registerType('tag', Tag, () => new Tag())

Dynamo createTransactionDynamo(JsonCodec json) {
  return createCommonDynamo(JSON)
    ..registerType('allMembersRequest', AllMembersRequest, () => new AllMembersRequest())
    ..registerType('allMembersResponse', AllMembersResponse, () => new AllMembersResponse())

Use this package as a library

1. Depend on it

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

  dynamo: ^0.1.0

2. Install it

You can install packages from the command line:

with pub:

$ pub get

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

3. Import it

Now in your Dart code, you can use:

import 'package:dynamo/dynamo.dart';
Version Uploaded Documentation Archive
0.1.0 Jan 20, 2017 Go to the documentation of dynamo 0.1.0 Download dynamo 0.1.0 archive
0.0.4 Jan 19, 2017 Go to the documentation of dynamo 0.0.4 Download dynamo 0.0.4 archive
0.0.2 Jan 17, 2017 Go to the documentation of dynamo 0.0.2 Download dynamo 0.0.2 archive
0.0.1 Jan 16, 2017 Go to the documentation of dynamo 0.0.1 Download dynamo 0.0.1 archive
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.

The package version is not analyzed, because it does not support Dart 2. Until this is resolved, the package will receive a health and maintenance score of 0.

Analysis issues and suggestions

Support Dart 2 in pubspec.yaml.

The SDK constraint in pubspec.yaml doesn't allow the Dart 2.0.0 release. For information about upgrading it to be Dart 2 compatible, please see https://dart.dev/dart-2#migration.

Maintenance issues and suggestions

Make sure dartdoc successfully runs on your package's source files. (-10 points)

Dependencies were not resolved.


Package Constraint Resolved Available
Direct dependencies
Dart SDK >=1.8.0 <2.0.0