douxin2011 2018-10-13 03:20
浏览 482
已采纳

Flutter用Golang RFC3339中的DateTime解析json:FormatException:无效的日期格式

When trying to read json files generated with golangs json package in Dart / Flutter I noticed that parsing dates produce an error:

FormatException: Invalid date format

An example is the following json generated on the Go server:

{
    ...
    "dateCreated": "2018-09-29T19:51:57.4139787-07:00",
    ...
}

I am using the code generation approach for json (de-)serialization to avoid writing all the boiler plate code. The json_serializable package is a standard package available for this purpose. So my code looks like the following:

@JsonSerializable()
class MyObj {

  DateTime dateCreated;

  MyObj( this.dateCreated);

  factory MyObj.fromJson(Map<String, dynamic> json) => _$MyObjFromJson(json);  
  Map<String, dynamic> toJson() => _$MyObjToJson(this); 
}
  • 写回答

2条回答 默认 最新

  • duangekui7451 2018-10-13 03:20
    关注

    Because the documentation doesn't cover this sufficiently it took me a day of researching the flutter sources and trial & error of different things to solve it. So may as well share it.

    Golang by default encodes the time.Time in RFC3339 when serializing to Json (like in the given example). Flutter explicitly supports RFC3339, so why doesn't it work? The answer is a small difference in how the seconds fraction part is supported. While Golang produces a precision of 7 digits Dart only supports up to 6 digits and does not gracefully handle violations. So if the example is corrected to only have 6 digits of precision it will parse just fine in Dart:

    {
        ...
        "dateCreated": "2018-09-29T19:51:57.413978-07:00",
        ...
    }
    

    In order to solve this in a generic way you have two options: 1. to truncate the additional precision from the string, or 2. implement your own parsing. Let's assume we extend the DateTime class and create your own CustomDateTime. The new class has the parse method overridden to remove all excess after 6 digits before handing it to the parent class' parse method.

    Now we can use the CustomDateTime in our Dart classes. For example:

    @JsonSerializable()
    class MyObj {
    
      CustomDateTime dateCreated;
    
      MyObj( this.dateCreated);
    
      factory MyObj.fromJson(Map<String, dynamic> json) => _$MyObjFromJson(json);  
      Map<String, dynamic> toJson() => _$MyObjToJson(this); 
    }
    

    But of course now the code generation is broken and we get the following error:

    Error running JsonSerializableGenerator
    Could not generate 'toJson' code for 'dateCreated'.
    None of the provided 'TypeHelper' instances support the defined type.
    

    Luckily the json_annotation package now has an easy solution for us - The JsonConverter. Here is how to use it in our example:

    First define a converter that explains to the code generator how to convert our CustomDateTime type:

    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();
    }
    

    Second we just annotate this converter to every class that is using our CustomDateTime data type:

    @JsonSerializable()
    @CustomDateTimeConverter()
    class MyObj {
    
      CustomDateTime dateCreated;
    
      MyObj( this.dateCreated);
    
      factory MyObj.fromJson(Map<String, dynamic> json) => _$MyObjFromJson(json);  
      Map<String, dynamic> toJson() => _$MyObjToJson(this); 
    }
    

    This satisfies the code generator and Voila! We can read json with RFC3339 timestamps that come from golang time.Time.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥15 请问一下这个运行结果是怎么来的
  • ¥15 这个复选框什么作用?
  • ¥15 单通道放大电路的工作原理
  • ¥30 YOLO检测微调结果p为1
  • ¥20 求快手直播间榜单匿名采集ID用户名简单能学会的
  • ¥15 DS18B20内部ADC模数转换器
  • ¥15 做个有关计算的小程序
  • ¥15 MPI读取tif文件无法正常给各进程分配路径
  • ¥15 如何用MATLAB实现以下三个公式(有相互嵌套)
  • ¥30 关于#算法#的问题:运用EViews第九版本进行一系列计量经济学的时间数列数据回归分析预测问题 求各位帮我解答一下