Introduction
This is "package:kind", a Dart package for creating static objects that describe "what kind of data" you have.
Licensed under the Apache License 2.0.
Links
Key features
- Flexible
- The package makes you think many things through, such as:
- How many bits an integer needs? 32? 52? 64?
- What is the maximum length of a list?
- When you convert
DateTimeinstances to/from JSON, should you use UTC or local time zone?
- Once you have specified your data model, the package lets you do:
- JSON serialization
- Database object mapping
- Automatic implementation of
==,hashCode, andtoString(). - And more!
- The package makes you think many things through, such as:
- No code generation.
- You write
Kind<T>specifications manually (see examples below). However, AI code assistants can easily automate the writing. - The package also works easily for any class. You don't need to modify the classes themselves. You could, for example, serialize Flutter SDK widgets.
- You write
Sounds interesting? We encourage you to compare this framework to older, more established packages such as json_serializable and pick your favorite.
Built-in kinds
- Fixed-length primitives
- Variable-length primitives
- Collection classes:
- Polymorphic values:
- User-defined classes:
- CompositeKind
- ImmutableKind
- Three possible constructors:
Things you can do
- Find classes
- Construct instances
- Validate data:
- Describe data:
- JSON serialization
- Reflection:
Getting started
1.Add dependency
In terminal, run the following in your project directory:
flutter pub add kind
Does not work? If your project uses Dart SDK rather than Flutter SDK, run dart pub add kind.
2.Study examples
See example code below.
Examples
import 'package:kind/kind.dart';
void main() {
//
// Encode/decode JSON trees:
//
final company = Company.kind.decodeJsonTree({
'name': 'Flutter App Development Experts',
'shareholders': [
{
'@type': 'Person',
'firstName': 'Alice',
'lastName': 'Smith',
},
{
'@type': 'Person',
'firstName': 'Bob',
},
],
});
print("${company.name} has ${company.shareholders.length} shareholders.");
//
// We have `==` and `hashCode` because we extended `HasKind`:
//
print(company.shareholders[1] == Person(firstName: 'Bob')); // --> true
//
// We have `toString()` because we extended `HasKind`:
//
print(company.toString());
// Prints:
// Company(
// "Flutter App Development Experts",
// shareholders: [
// Person(
// firstName: 'John',
// lastName: 'Doe',
// ),
// Person(firstName: 'Bob'),
// ],
// )
}
//
// Example class #1:
// "A static `_walk` function"
//
class Company extends Shareholder {
static const kind = ImmutableKind<Company>(
name: 'Company',
blank: Company(''),
walk: _walk,
);
@override
final String name;
final List<Shareholder> shareholders;
const Company(this.name, {this.shareholders = const []});
@override
Kind<Company> get runtimeKind => kind;
static Company _walk(Mapper f, Company t) {
final name = f.positional(t.name, 'name');
final shareholders = f(
t.shareholders,
'shareholders',
kind: const ListKind(
elementKind: Shareholder.kind,
),
);
// The following is a performance optimization we recommend:
if (f.canReturnSame) {
return t;
}
// Finally, construct a new instance:
return Company(
name,
shareholders: shareholders,
);
}
}
//
// Example #2:
// "A class that extends `Walkable`"
//
class Person extends Shareholder with Walkable {
static const kind = ImmutableKind<Person>.walkable(
name: 'Person',
blank: Person(firstName: ''),
);
/// First name
final String firstName;
/// First name
final String lastName;
const Person({
required this.firstName,
this.lastName = '',
});
@override
String get name => '$firstName $lastName';
@override
Kind<Person> get runtimeKind => kind;
@override
Person walk(Mapper f) {
final firstName = f.required(
this.firstName,
'firstName',
kind: const StringKind.singleLineShort(),
);
final lastName = f(
this.lastName,
'lastName',
kind: const StringKind.singleLineShort(),
);
if (f.canReturnSame) {
return this;
}
return Person(
firstName: firstName,
lastName: lastName,
);
}
}
//
// Example #3:
// "A polymorphic class"
//
abstract class Shareholder extends HasKind {
static const kind = PolymorphicKind<Shareholder>.sealed(
defaultKinds: [
Person.kind,
Company.kind,
],
);
const Shareholder();
String get name;
}
Libraries
- kind
- A data reflection and serialization library.