代码之家  ›  专栏  ›  技术社区  ›  Oswin Noetzelmann

flatter解析来自Golang rfc339的带有DateTime的json:FormatException:无效的日期格式

  •  0
  • Oswin Noetzelmann  · 技术社区  · 7 年前

    FormatException: Invalid date format
    

    例如,在Go服务器上生成的json如下:

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

    我使用json(反)序列化的代码生成方法来避免编写所有的锅炉板代码。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); 
    }
    
    1 回复  |  直到 7 年前
        1
  •  4
  •   Oswin Noetzelmann    7 年前

    因为文档中没有充分说明这一点,所以我花了一天的时间研究颤振源和试验;解决不同事物的错误。所以不妨分享一下。

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

    为了以通用的方式解决这个问题,您有两个选项:1.从字符串中截断额外的精度,或2.实现您自己的解析。假设我们扩展了 DateTime CustomDateTime . 新班级有 parse 方法重写以在将其交给父类的parse方法之前删除6位之后的所有多余部分。

    自定义日期时间

    @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 . 下面是如何在我们的示例中使用它:

    首先定义一个转换器,向代码生成器解释如何转换 自定义日期时间 类型:

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

    其次,我们只需将此转换器注释到使用CustomDateTime数据类型的每个类:

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

    这满足了代码生成器的要求,瞧!我们可以从golang time.time读取带有rfc339时间戳的json。

        2
  •  4
  •   harmonica141 tsvikas    7 年前

    我也有同样的问题。我找到了一个非常简单的解决办法。我们可以将自定义转换器与JsonConverter一起使用。更多的解释你可以用我的 article .

    import 'package:json_annotation/json_annotation.dart';
    
    class CustomDateTimeConverter implements JsonConverter<DateTime, String> {
      const CustomDateTimeConverter();
    
      @override
      DateTime fromJson(String json) {
        if (json.contains(".")) {
          json = json.substring(0, json.length - 1);
        }
    
        return DateTime.parse(json);
      }
    
      @override
      String toJson(DateTime json) => json.toIso8601String();
    }
    

    import 'package:json_annotation/json_annotation.dart';
    import 'package:my_app/shared/helpers/custom_datetime.dart';
    
    part 'publication_document.g.dart';
    
    @JsonSerializable()
    @CustomDateTimeConverter()
    class PublicationDocument {
      final int id;
      final int publicationId;
    
      final DateTime publicationDate;
      final DateTime createTime;
      final DateTime updateTime;
      final bool isFree;
    
      PublicationDocument({
        this.id,
        this.publicationId,
        this.publicationDate,
        this.createTime,
        this.updateTime,
        this.isFree,
      });
    
      factory PublicationDocument.fromJson(Map<String, dynamic> json) =>
          _$PublicationDocumentFromJson(json);
      Map<String, dynamic> toJson() => _$PublicationDocumentToJson(this);
    }