我尝试将对象转换为JSON.
var obj = { "dt": new DateTime.now() };
var s = stringify(obj);
Run Code Online (Sandbox Code Playgroud)
运行时抛出异常:"在对象上调用toJson方法失败."
这是预期的,因为DateTime类没有toJson方法.但在这种情况下我该怎么办?
Javascript的JSON.stringify函数有一个可选的参数替换器,它允许我提供我自己的任何对象序列化方法,即使该对象没有toJson方法.在Dart中是否有任何类似的工具,或者我可以使用自己的toJson方法以某种方式扩展DateTime类?
Sur*_*gch 14
JSON 转换仅适用于映射、列表、字符串、数字、布尔值或 null。那么,如果您的对象包含另一种类型,例如DateTime?
让我们从以下对象开始:
class Person {
Person(this.name, this.birthdate);
String name;
DateTime birthdate;
}
Run Code Online (Sandbox Code Playgroud)
您可以将其转换为这样的地图:
final person = Person('Bob', DateTime(2020, 2, 25));
Map<String, dynamic> map = {
'name': person.name,
'birthdate': person.birthdate,
};
Run Code Online (Sandbox Code Playgroud)
如果您现在尝试使用jsonEncode(或json.encode)对其进行编码,则会出现错误,因为DateTime不能直接序列化。有两种解决方案。
你可以先像这样自己序列化它:
Map<String, dynamic> map = {
'name': person.name,
'birthdate': person.birthdate.toIso8601String(),
};
final jsonString = json.encode(map);
Run Code Online (Sandbox Code Playgroud)
笔记:
这里的区别toString和toIso8601String:
2020-02-25 14:44:28.534 // toString()
2020-02-25T14:44:28.534 // toIso8601String()
Run Code Online (Sandbox Code Playgroud)
在toIso8601String没有任何空间,这样使得它更好的转化率和发送过可能不带空格处理良好的API。
您可以在 上使用可选的toEncodable函数参数jsonEncode。
import 'dart:convert';
void main() {
final person = Person('Bob', DateTime(2020, 2, 25));
Map<String, dynamic> map = {
'name': person.name,
'birthdate': person.birthdate,
};
final toJson = json.encode(map, toEncodable: myDateSerializer);
}
dynamic myDateSerializer(dynamic object) {
if (object is DateTime) {
return object.toIso8601String();
}
return object;
}
Run Code Online (Sandbox Code Playgroud)
该toEncodable函数只是将输入转换为字符串或jsonEncode可以转换为字符串的内容。
这里没有什么特别的。您只需要将字符串解析为您需要的类型。在这种情况下,DateTime您可以使用它的parse或tryParse方法。
final myMap= json.decode(jsonString);
final name = myMap['name'];
final birthdateString = myMap['birthdate'];
final birthdate = DateTime.parse(birthdateString);
final decodedPerson = Person(name, birthdate);
Run Code Online (Sandbox Code Playgroud)
请注意,parse如果字符串的格式无法解析为DateTime对象,则会抛出异常。
class Person {
Person(this.name, this.birthdate);
String name;
DateTime birthdate;
Person.fromJson(Map<String, dynamic> json)
: name = json['name'],
birthdate = DateTime.tryParse(json['birthdate']),
Map<String, dynamic> toJson() {
return {
'name': name,
'birthdate': birthdate.toIso8601String(),
};
}
}
Run Code Online (Sandbox Code Playgroud)
如果日期格式错误,这不会引发异常,但birthdate会是null.
dart:jsonIMO,这是库中的一个缺陷,stringify不支持额外的回调来序列化缺乏toJson. 奇怪的是,parse函数确实支持reviver参数来自定义反序列化过程。可能的原因是用户可以toJson为其添加类型,核心库将处理“本机”类型,但DateTime被省略了(可能是因为 JSON 中的日期序列化并不是一个简单的故事)。
也许团队的目标是使用自定义类型而不是 Map(这很好),但这里的缺点是,如果您的自定义类型包含 10 个其他属性和 1 个类型DateTime,则您需要实现toJson将所有这些属性序列化,甚至整数和字符串。希望一旦 Mirror API 准备就绪,就会有库通过读取类型的反射信息来实现“带外”序列化,请参阅下面的示例。Dart 的承诺是我能够在服务器和客户端上使用我的类型,但是如果我必须为我的所有模型手动实现序列化/反序列化,那么它就太尴尬了而无法使用。
它本身在格式化方面不太灵活也无济于事,因为除了返回对序列化无用的格式DateTime之外,没有其他方法。toString
所以这里有一些选择:
DateTime该类型提供toJsonjson.stringifyJsonValue并提交更改或至少提交一个问题:)json-object(只是一个例子,它也不支持DateTime序列化,AFAIK我对他们中的任何一个都不满意:)
| 归档时间: |
|
| 查看次数: |
2025 次 |
| 最近记录: |