Flutter使用Freezed序列化时类型不匹配的DateTime字段如何设为null
解决方案
方案1:针对单个字段自定义解析逻辑
适合项目中DateTime类型字段较少的场景,直接给对应字段加自定义解析函数即可:
首先定义通用的DateTime容错解析函数:
/// 容错解析DateTime,类型不匹配时直接返回null DateTime? _dateTimeFromJson(dynamic value) { // 兼容int类型时间戳,可根据后端实际时间戳单位调整(秒级/毫秒级) if (value is int) { // 示例为秒级时间戳转DateTime,毫秒级时间戳直接去掉 *1000 即可 return DateTime.fromMillisecondsSinceEpoch(value * 1000); } // 兼容标准ISO格式时间字符串 if (value is String) { return DateTime.tryParse(value); } // 其他不匹配类型直接返回null,不会抛出异常 return null; }
然后在对应字段的@JsonKey注解中绑定该解析函数:
@freezed class Block with _$Block { const factory Block({ @JsonKey(name: 'block_id') required String id, @JsonKey(name: 'sent_at', fromJson: _dateTimeFromJson) DateTime? sentAt, @JsonKey(name: 'created_at', fromJson: _dateTimeFromJson) DateTime? createdAt, }) = _Block; factory Block.fromJson(Map<String, dynamic> json) => _$BlockFromJson(json); }
方案2:全局JsonConverter统一处理
如果项目中大量实体类都有DateTime?类型字段,可通过全局转换器统一处理,无需给每个字段单独加注解:
首先自定义全局DateTime转换器:
import 'package:json_annotation/json_annotation.dart'; class SafeDateTimeConverter implements JsonConverter<DateTime?, dynamic> { const SafeDateTimeConverter(); @override DateTime? fromJson(dynamic value) { if (value is int) { // 可根据实际业务调整时间戳单位 return DateTime.fromMillisecondsSinceEpoch(value * 1000); } if (value is String) { return DateTime.tryParse(value); } return null; } @override dynamic toJson(DateTime? dateTime) => dateTime?.toIso8601String(); }
之后只需要在需要生效的实体类上添加该转换器注解即可,类内所有DateTime?字段都会自动应用容错逻辑:
@freezed @SafeDateTimeConverter() // 应用全局容错转换器 class Block with _$Block { const factory Block({ @JsonKey(name: 'block_id') required String id, @JsonKey(name: 'sent_at') DateTime? sentAt, @JsonKey(name: 'created_at') DateTime? createdAt, }) = _Block; factory Block.fromJson(Map<String, dynamic> json) => _$BlockFromJson(json); }
内容的提问来源于stack exchange,提问作者Ahmed Bassiouny
相关产品推荐
相关产品推荐

