dynamo 0.1.0

  • README.md
  • CHANGELOG.md
  • Installing
  • Versions
  • 44

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.

@DynamoSerializable()
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();

  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 }

@DynamoSerializable()
class Member extends Object with _$MemberDynamoMixin {

  MemberType type;

  Member();

}

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
  };

  @override
  bool canDecode(value) => value is MemberType;

  @override
  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
    
      MemberTransformer(this.members);
    
      @override
      bool canEncode(value) => value is Member;
    
      @override
      encode(Member value) => {KEY: value.id};
    
      @override
      bool canDecode(value) => value is Map && value.containsKey(KEY);
    
      @override
      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()
      ..addTransformer(memberTransformer)
    ;

    var output = dynamo.toJson(m2);

will produce:

  {"memberId":2}

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

[
  {"_dt_":"2017-01-29T00:00:00.000Z"},
  {"_dt_":"2017-01-28T00:00:00.000Z"}
]

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

{
    "_isa_":"member",
    "registered":{"_dt_":"2017-01-30T00:00:00.000Z"}
}

instead of (using internal datetime transformers for fields):

{
    "_isa_":"member",
    "registered":"2017-01-30T00:00:00.000Z"
}

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:

[
  {
    "_isa_":"member",
    "_id#_":1
  },
  {"_ref_":1}
]

To customize these key use following setters:

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

Same example will produce:

[
  {
    "$typeof":"member",
    "$instance":1
  },
  {"$reference":1}
]

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

1. Depend on it

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


dependencies:
  dynamo: "^0.1.0"

2. Install it

You can install packages from the command line:

with pub:


$ pub get

with Flutter:


$ flutter packages get

Alternatively, your editor might support pub get or packages 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

Analysis

We analyzed this package on Apr 23, 2018, and provided a score, details, and suggestions below. Analysis was completed with status completed using:

  • Dart: 2.0.0-dev.49.0
  • pana: 0.10.6

Scores

Popularity:
Describes how popular the package is relative to other packages. [more]
0 / 100
Health:
Code health derived from static analysis. [more]
98 / 100
Maintenance:
Reflects how tidy and up-to-date the package is. [more]
74 / 100
Overall score:
Weighted score of the above. [more]
44
Learn more about scoring.

Platforms

Detected platforms: Flutter, web, other

No platform restriction found in primary library package:dynamo/dynamo.dart.

Suggestions

  • The description is too short.

    Add more detail about the package, what it does and what is its target use case. Try to write at least 60 characters.

  • Package is pre-v1 release.

    While there is nothing inherently wrong with versions of 0.*.*, it usually means that the author is still experimenting with the general direction API.

  • Fix analysis and formatting issues.

    Analysis or formatting checks reported 9 hints.

    Run dartfmt to format lib/dynamo.dart.

    Run dartfmt to format lib/dynamo_generator.dart.

    Similar analysis of the following files failed:

    • lib/src/decoding.dart (hint)
    • lib/src/encoding.dart (hint)
    • lib/src/protocol.dart (hint)
    • lib/src/serializer.dart (hint)
    • lib/src/transformers.dart (hint)
  • Use analysis_options.yaml.

    Rename old .analysis_options file to analysis_options.yaml.

Dependencies

Package Constraint Resolved Available
Direct dependencies
Dart SDK >=1.8.0 <2.0.0
build >=0.2.1 <0.7.0 0.6.3 0.12.2
logging >=0.11.3+1 <0.12.0 0.11.3+1
source_gen >=0.5.3 <0.6.0 0.5.3+2 0.8.1
Transitive dependencies
analyzer 0.29.11 0.31.1
args 0.13.7 1.4.2
async 2.0.6
charcode 1.1.1
cli_util 0.0.1+2 0.1.2+1
collection 1.14.9
convert 2.0.1
crypto 2.0.2+1
csslib 0.14.1
dart_style 0.2.16 1.0.10
glob 1.1.5
html 0.13.3
isolate 1.1.0 2.0.0
meta 1.1.2
package_config 1.0.3
path 1.5.1
plugin 0.2.0+2
source_span 1.4.0
string_scanner 1.0.2
typed_data 1.1.5
utf 0.9.0+4
watcher 0.9.7+7
when 0.2.0
which 0.1.3
yaml 2.1.13
Dev dependencies
build_runner ^0.1.0
build_test ^0.3.0
test any