JSON 转换仅适用于地图、列表、字符串、数字、布尔或 null。那么如果您的对象包含另一种类型,例如 DateTime
?
DateTime → JSON
让我们从以下对象开始:
class Person {
Person(this.name, this.birthdate);
String name;
DateTime birthdate;
}
你可以像这样将它转换为一个地图:
final person = Person('Bob', DateTime(2020, 2, 25));
Map<String, dynamic> map = {
'name': person.name,
'birthdate': person.birthdate,
};
如果您现在尝试使用jsonEncode
(或json.encode
)对此进行编码,您将会收到一个错误,因为DateTime
不能直接序列化。有两个解决方案。
解决方案1
您可以首先自己序列化它,像这样:
Map<String, dynamic> map = {
'name': person.name,
'birthdate': person.birthdate.toIso8601String(),
};
final jsonString = json.encode(map);
Note:
这里是 toString
和 toIso8601String
之间的区别:
2020-02-25 14:44:28.534 // toString()
2020-02-25T14:44:28.534 // toIso8601String()
toIso8601String
没有任何空格,这使得它更适合于转换和发送到可能无法处理空格的API上。
解决方案2
您可以在jsonEncode
上使用可选的toEncodable
函数参数。
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;
}
toEncodable
函数只是将输入转换为字符串或可转换为字符串的内容,以便 jsonEncode
可以将其转换为字符串。
JSON → DateTime
这里没有什么特别的。你只需要将字符串解析成需要的类型即可。在 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);
请注意,如果字符串的格式无法解析为DateTime
对象,则parse
会抛出异常。
作为模型类
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(),
};
}
}
如果日期格式错误,这不会引发异常,但birthdate
将为null
。
备注
- 请参见此处获取我的详细回答。
- 感谢此答案指导我正确的方向。
intl
。需要一个好的序列化库,但我想在镜像API完成之前没有意义。 - Zdeslav VojkovicDateFormat
上。因此,它需要成为我的代码中的单独函数(或硬编码实例),这意味着数据格式化在DateTime、DateFormat和我的函数/实例之间分散。 - Zdeslav VojkovicMap
,如果其中包含一个DateTime
字段,则会遇到相同的问题。由于DateTime
经常被使用,我认为应该扩展 'json.stringify' 来支持它(例如以 RFC3339 UTC 格式)。 - Zdeslav Vojkovic