schemantic

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Schemantic

Schemantic

Schemantic is a general-purpose Dart library used for defining strongly typed data classes that automatically bind to reusable runtime JSON schemas. It is standard for the
genkit-dart
framework but works independently as well.
Schemantic是一个通用的Dart库,用于定义可自动绑定到可复用运行时JSON模式的强类型数据类。它是
genkit-dart
框架的标准组件,但也可以独立使用。

Core Concepts

核心概念

Always use
schemantic
when strongly typed JSON parsing or programmatic schema validation is required.
  • Annotate your abstract classes with
    @Schematic()
    .
  • Use the
    $
    prefix for abstract schema class names (e.g.,
    abstract class $User
    ).
  • Always run
    dart run build_runner build
    to generate the
    .g.dart
    schema files.
当需要强类型JSON解析或程序化模式验证时,请始终使用
schemantic
  • @Schematic()
    注解你的抽象类。
  • 抽象模式类名使用
    $
    前缀(例如:
    abstract class $User
    )。
  • 务必运行
    dart run build_runner build
    来生成
    .g.dart
    模式文件。

Basic Usage

基础用法

  1. Defining a schema:
dart
import 'package:schemantic/schemantic.dart';

part 'my_file.g.dart'; // Must match the filename

()
abstract class $MyObj {
  String get name;
  $MySubObj get subObj;
}

()
abstract class $MySubObj {
  String get foo;
}
  1. Using the Generated Class:
The builder creates a concrete class
MyObj
(no
$
) with a factory constructor (
MyObj.fromJson
) and a regular constructor.
dart
// Creating an instance
final obj = MyObj(name: 'test', subObj: MySubObj(foo: 'bar'));

// Serializing to JSON
print(obj.toJson()); 

// Parsing from JSON
final parsed = MyObj.fromJson({'name': 'test', 'subObj': {'foo': 'bar'}});
  1. Accessing Schemas at Runtime:
The generated data classes have a static
$schema
field (of type
SchemanticType<T>
) which can be used to pass the definition into functions or to extract the raw JSON schema.
dart
// Access JSON schema
final schema = MyObj.$schema.jsonSchema;
print(schema.toJson());

// Validate arbitrary JSON at runtime
final validationErrors = await schema.validate({'invalid': 'data'});
  1. 定义模式:
dart
import 'package:schemantic/schemantic.dart';

part 'my_file.g.dart'; // 必须与文件名匹配

()
abstract class $MyObj {
  String get name;
  $MySubObj get subObj;
}

()
abstract class $MySubObj {
  String get foo;
}
  1. 使用生成的类:
构建器会创建一个不带
$
的具体类
MyObj
,包含工厂构造函数(
MyObj.fromJson
)和常规构造函数。
dart
// 创建实例
final obj = MyObj(name: 'test', subObj: MySubObj(foo: 'bar'));

// 序列化为JSON
print(obj.toJson()); 

// 从JSON解析
final parsed = MyObj.fromJson({'name': 'test', 'subObj': {'foo': 'bar'}});
  1. 在运行时访问模式:
生成的数据类包含一个静态
$schema
字段(类型为
SchemanticType<T>
),可用于将定义传入函数或提取原始JSON模式。
dart
// 访问JSON模式
final schema = MyObj.$schema.jsonSchema;
print(schema.toJson());

// 在运行时验证任意JSON
final validationErrors = await schema.validate({'invalid': 'data'});

Primitive Schemas

原始类型模式

When a full data class is not required, Schemantic provides functions to create schemas dynamically.
dart
final ageSchema = intSchema(description: 'Age in years', minimum: 0);
final nameSchema = stringSchema(minLength: 2);
final nothingSchema = voidSchema();
final anySchema = dynamicSchema();

final userSchema = mapSchema(stringSchema(), intSchema()); // Map<String, int>
final tagsSchema = listSchema(stringSchema()); // List<String>
当不需要完整数据类时,Schemantic提供了动态创建模式的函数。
dart
final ageSchema = intSchema(description: 'Age in years', minimum: 0);
final nameSchema = stringSchema(minLength: 2);
final nothingSchema = voidSchema();
final anySchema = dynamicSchema();

final userSchema = mapSchema(stringSchema(), intSchema()); // Map<String, int>
final tagsSchema = listSchema(stringSchema()); // List<String>

Union Types (AnyOf)

联合类型(AnyOf)

To allow a field to accept multiple types, use
@AnyOf
.
dart
()
abstract class $Poly {
  ([int, String, $MyObj])
  Object? get id;
}
Schemantic generates a specific helper class (e.g.,
PolyId
) to handle the values:
dart
final poly1 = Poly(id: PolyId.int(123));
final poly2 = Poly(id: PolyId.string('abc'));
要允许字段接受多种类型,请使用
@AnyOf
dart
()
abstract class $Poly {
  ([int, String, $MyObj])
  Object? get id;
}
Schemantic会生成一个特定的辅助类(例如
PolyId
)来处理这些值:
dart
final poly1 = Poly(id: PolyId.int(123));
final poly2 = Poly(id: PolyId.string('abc'));

Field Annotations

字段注解

You can use specialized annotations for more validation boundaries:
dart
()
abstract class $User {
  (
    name: 'years_old', // Change JSON key
    description: 'Age of the user',
    minimum: 0,
    defaultValue: 18,
  )
  int? get age;

  (
    minLength: 2,
    enumValues: ['user', 'admin'], 
  )
  String get role;
}
你可以使用专用注解来设置更多验证边界:
dart
()
abstract class $User {
  (
    name: 'years_old', // 修改JSON键名
    description: '用户年龄',
    minimum: 0,
    defaultValue: 18,
  )
  int? get age;

  (
    minLength: 2,
    enumValues: ['user', 'admin'], 
  )
  String get role;
}

Recursive Schemas

递归模式

For recursive structures (like trees), must use
useRefs: true
inside the generated jsonSchema property. You define it normally:
dart
()
abstract class $Node {
  String get id;
  List<$Node>? get children;
}
Note:
Node.$schema.jsonSchema(useRefs: true)
generates schemas with JSON Schema
$ref
.
对于递归结构(如树),必须在生成的jsonSchema属性中使用
useRefs: true
。定义方式保持正常:
dart
()
abstract class $Node {
  String get id;
  List<$Node>? get children;
}
注意
Node.$schema.jsonSchema(useRefs: true)
会生成带有JSON Schema
$ref
的模式。