Serialization
Last updated
Last updated
Source-generated serialization for Dart objects. This package uses package:source_gen
to eliminate the time you spend writing boilerplate serialization code for your models. package:angel3_serialize
also powers package:angel3_orm
.
In your pubspec.yaml
, you need to install the following dependencies:
With the recent updates to package:build_runner
, you can build models automatically, anywhere in your project structure, by running pub run build_runner build
.
To tweak this: Build Config
If you want to watch for file changes and re-build when necessary, replace the build
call with a call to watch
. They take the same parameters.
There are a few changes opposed to normal Model classes. You need to add a @serializable
annotation to your model class to have it serialized, and a serializable model class's name should also start with a leading underscore.
In addition, you may consider using an abstract
class to ensure immutability of models.
Rather you writing the public class, angel3_serialize
does it for you. This means that the main class can have its constructors automatically generated, in addition into serialization functions.
For example, say we have a Book
model. Create a class named _Book
:
The following file will be generated:
book.g.dart
Producing these classes:
Book
: Extends or implements _Book
; may be const
-enabled.
BookSerializer
: static functionality for serializing Book
models.
BookFields
: The names of all fields from the Book
model, statically-available.
BookEncoder
: Allows BookSerializer
to extend Codec<Book, Map>
.
BookDecoder
: Also allows BookSerializer
to extend Codec<Book, Map>
.
And the following other features:
bookSerializer
: A top-level, const
instance of BookSerializer
.
Book.toString
: Prints out all of a Book
instance's fields.
You can use the generated files as follows:
As of 2.0.2
, the generated output also includes information about the serialized names of keys on your model class.
Currently, these serialization methods are supported:
to Map
to JSON
to TypeScript definitions
You can customize these by means of serializers
:
angel3_serialize
pulls in fields from parent classes, as well as implemented interfaces, so it is extremely easy to share attributes among model classes:
Whereas Dart fields conventionally are camelCased, most database columns tend to be snake_cased. This is not a problem, because we can define an alias for a field.
By default angel3_serialize
will transform keys into snake case. Use alias
to provide a custom name, or pass autoSnakeCaseNames
: false
to the builder;
You can also override autoSnakeCaseNames
per model:
In pratice, there may keys that you want to exclude from JSON. To accomplish this, simply annotate them with @exclude
:
There are times, however, when you want to only exclude either serialization or deserialization, but not both. For example, you might want to deserialize passwords from a database without sending them to users as JSON.
In this case, use canSerialize
or canDeserialize
:
It is easy to mark a field as required:
The given field will be marked as @required
in the generated constructor, and serializers will check for its presence, throwing a FormatException
if it is missing.
There are times when you need the generated class to have annotations affixed to it:
package:angel3_serialize
does not cover every known Dart data type; you can add support for your own. Provide serializer
and deserializer
arguments to @SerializableField()
as you see fit.
They are typically used together. Note that the argument to deserializer
will always be dynamic
, while serializer
can receive the data type in question.
In such a case, you might want to also provide a serializesTo
argument. This lets the generator, as well as the ORM, apply the correct (de)serialization rules and validations.
angel3_serialize
also supports a few types of nesting of @serializable
classes:
As a class member, ex. Book myField
As the type argument to a List
, ex. List<Book>
As the second type argument to a Map
, ex. Map<String, Book>
In other words, the following are all legal, and will be serialized/deserialized. You can use either the underscored name of a child class (ex. _Book
), or the generated class name (ex Book
):
If your model (Author
) depends on a model defined in another file (Book
), then you will need to generate book.g.dart
before, author.g.dart
, in a separate build action. This way, the analyzer can resolve the Book
type.
This package will automatically generate id
, createdAt
, and updatedAt
fields for you, in the style of an Angel3 Model
. This will automatically be generated, only for classes extending Model
.
package:angel3_serialize
also handles Uint8List
fields, by means of serialization to and from base64
encoding.
It is quite common to build frontends with JavaScript and/or TypeScript, so why not generate typings as well?
To accomplish this, add Serializers.typescript
to your @Serializable()
declaration:
The aforementioned _Author
class will generate the following in author.d.ts
:
Fields with an @Exclude()
that specifies canSerialize: false
will not be present in the TypeScript definition. The rationale for this is that if a field (i.e. password
) will never be sent to the client, the client shouldn't even know the field exists.
Sometimes, you may need to have custom constructor parameters, for example, when using depedency injection frameworks. For these cases, angel3_serialize
can forward custom constructor parameters.
The following:
Generates: