使用来自Golang RFC3339的DateTime来解析json:FormatException:无效的日期格式

问题描述 投票:1回答:2

当尝试读取在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 go dart flutter
2个回答
4
投票

因为文档没有充分涵盖这一点,所以我花了一天时间研究颤振源和不同事物的反复试验来解决它。所以不妨分享一下。

当序列化为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。


1
投票

我也有同样的问题。我发现了一个很简单的解决方案我们可以使用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
© www.soinside.com 2019 - 2024. All rights reserved.