ManagedObject 的序列化和反序列化
在本指南中,您将学习如何从HTTP请求体中读取 "ManagedObject
基本转换
ManagedObject<T>
可以转换为Map<String, dynamic>
对象,也可以从Map<String, dynamic>
对象中转换。每个键都是对象中的一个属性的名称。要将一个ManagedObject
解码为Map
,请调用它的read
方法
final object = MyManagedObject();
object.read({
"key": "value"
});
// object.key == "value"
当输入数据无效时,会抛出验证异常(状态代码:400):如果一个键没有相应的属性,值的类型与预期的类型不匹配,或者违反了管理对象的某些约束。
筛选器可以应用于被读对象的键值。过滤器可以忽略键,要求键,或者在存在键的情况下抛出一个异常。下面是一个例子,在这个例子中,由于'id'是必需的,但没有提供,所以读取会抛出一个异常。
object.read({
"key": "value"
}, require: ["id"]);
ManagedObjects继承Serializable
read
方法和它的过滤器继承自Serializable
,这里将详细讨论。被管理的对象,就像可序列化对象一样,可以被绑定到操作方法参数中。
管理的对象有一个默认键的列表,可以作为基础过滤器集。
object.read({}, require: object.entity.defaultProperties);
要将一个被管理对象序列化为map,请使用实例方法asMap
:
final object = MyManagedObject();
Map<String, dynamic> map = object.asMap();
如果对象上的属性没有被设置,那么它将不会被写到map中。
等同于管理对象的“ Map”的值始终是原始值,可以将其编码为JSON,通过isolate对象进行发送等。以下显示了序列化格式的表:
Dart Type | Serialized Type |
---|---|
int |
number (int ) |
double |
number (double ) |
String |
string (String ) |
DateTime |
ISO 8601 Timestamp (String ) |
bool |
boolean (bool ) |
Document |
map or list (Map<String, dynamic> or List<dynamic> ) |
Any enum |
string (String ) |
Belongs-To or Has-One Relationship | map (Map<String, dynamic> ) |
Has-Many Relationship | list of maps (List<Map<String, dynamic>> ) |
Null 值的行为
一个被管理对象的属性可以为null,原因有两个:值实际上为null,或者值不可用。例如,当你创建一个新的被管理对象的实例时,它的值没有一个是可用的(该对象是空的)。当将一个对象编码成映射时,只包含可用的值,而省略了任何不可用属性的键。
final myObject = MyManagedObject(); // empty object
myObject.asMap() == {}; // true
myObject.id = 1;
myObject.asMap() == {
"id": 1
}; // true
仅当属性值确实为null时,托管对象的asMap
中的值才为null:
myObject.id = null;
myObject.asMap() == {
"id": null
}; // true
通过访问器设置属性值,使用read
或从查询返回对象时,属性值才可用。
瞬态属性的行为
默认情况下,对象的asMap()
中不包含瞬态属性(在托管对象子类中声明的属性,而不是表定义中声明的属性)。 Serialize
注解允许在此映射中包含一个瞬态属性。
class Employee extends ManagedObject<_Employee> implements _Employee {
int a; // NOT included in asMap, NOT read in read
@Serialize()
int b; // included in asMap, read in read
@Serialize(input: true, output: false)
int c; // NOT included in asMap, read in read
@Serialize(input: false, output: true)
int d; // included in asMap, NOT read in read
}
class _Employee {
@primaryKey
int id;
}
可能存在单独的getter和setter而不是属性。 有了这个注解,getter被添加到asMap
中,并且setter将被输入到read
中。
class User extends ManagedObject<_User> implements _User {
@Serialize()
set transientValue(String s) {
...
}
@Serialize()
String get transientValue => ...;
}
如果瞬态属性的键值为null,则不会在asMap()
中出现。
关系属性的行为
对托管对象进行编码时,关系属性被表示为map(对于属于或具有has-one关系)或map列表(对于具有has-many关系)。 属性的可用性规则同样适用于关系属性。 下面显示了一个示例map,该map映射了具有适当命名的关系属性的托管对象:
{
"id": 1,
"belongsTo": {
"id": 1
},
"hasOne": {
"id": 2,
"name": "Fred"
},
"hasMany": [
{"id": 3, "name": "Bob"},
{"id": 4, "name": "Joe"},
]
}
belongs-to关系永远是一个映射关系。这对于经常创建或更新对象的所属关系的客户端应用程序很重要。 例如,希望创建一个名为Timmy的子对象且其父对象的id == 1
的客户端将发送以下JSON:
{
"name": "Timmy",
"parent": {
"id": 1
}
}
这与某些可以使这种结构扁平化的框架不同,例如:
{
"name": "Timmy",
"parent_id": 1
}