当尝试读取在Dart / Flutter中使用golangs json包生成的json文件时,我注意到解析日期会产生错误:
FormatException: Invalid date format
一个例子是Go服务器上生成的以下json:
{
...
"dateCreated": "2018-09-29T19:51:57.4139787-07:00",
...
}
我正在使用json(de)序列化的代码生成方法来避免编写所有的锅炉板代码。 json_serializable包是可用于此目的的标准包。所以我的代码如下所示:
@JsonSerializable()
class MyObj {
DateTime dateCreated;
MyObj( this.dateCreated);
factory MyObj.fromJson(Map<String, dynamic> json) => _$MyObjFromJson(json);
Map<String, dynamic> toJson() => _$MyObjToJson(this);
}
因为文档没有充分涵盖这一点,所以我花了一天时间研究颤振源和不同事物的反复试验来解决它。所以不妨分享一下。
当序列化为Json时,Golang默认编码RFC3339中的time.Time(如给定示例中所示)。 Flutter明确支持RFC3339,为什么它不起作用?答案是如何支持秒分数部分的微小差异。虽然Golang产生7位数的精度,Dart仅支持最多6位数,并且不能优雅地处理违规。因此,如果示例被更正为只有6位数的精度,它将在Dart中解析得很好:
{
...
"dateCreated": "2018-09-29T19:51:57.413978-07:00",
...
}
为了以通用方式解决这个问题,您有两个选择:1。从字符串中截断附加精度,或2.实现自己的解析。让我们假设我们扩展DateTime
类并创建自己的CustomDateTime
。在将类交给父类的解析方法之前,新类将覆盖parse
方法以删除6位数之后的所有多余数据。
现在我们可以在Dart课程中使用CustomDateTime
。例如:
@JsonSerializable()
class MyObj {
CustomDateTime dateCreated;
MyObj( this.dateCreated);
factory MyObj.fromJson(Map<String, dynamic> json) => _$MyObjFromJson(json);
Map<String, dynamic> toJson() => _$MyObjToJson(this);
}
但是当然现在代码生成被破坏了,我们得到以下错误:
Error running JsonSerializableGenerator
Could not generate 'toJson' code for 'dateCreated'.
None of the provided 'TypeHelper' instances support the defined type.
幸运的是,json_annotation
包现在为我们提供了一个简单的解决方案 - JsonConverter
。以下是在我们的示例中如何使用它:
首先定义一个转换器,向代码生成器解释如何转换qazxsw poi类型:
CustomDateTime
其次,我们只是将这个转换器注释到使用Custom DateTime数据类型的每个类:
class CustomDateTimeConverter implements JsonConverter<CustomDateTime, String> {
const CustomDateTimeConverter();
@override
CustomDateTime fromJson(String json) =>
json == null ? null : CustomDateTime.parse(json);
@override
String toJson(CustomDateTime object) => object.toIso8601String();
}
这满足代码生成器和Voila!我们可以使用来自golang time.Time的RFC3339时间戳来读取json。
我也有同样的问题。我发现了一个很简单的解决方案我们可以使用JsonConverter的自定义转换器。有关更多说明,您可以使用我的qazxsw poi。
@JsonSerializable()
@CustomDateTimeConverter()
class MyObj {
CustomDateTime dateCreated;
MyObj( this.dateCreated);
factory MyObj.fromJson(Map<String, dynamic> json) => _$MyObjFromJson(json);
Map<String, dynamic> toJson() => _$MyObjToJson(this);
}
article