【问题标题】:Unhandled Exception: Converting object to an encodable object failed: Instance of 'DateTime'未处理的异常:将对象转换为可编码对象失败:“日期时间”实例
【发布时间】:2021-04-16 20:28:59
【问题描述】:

我有一个任务模型 =>

class Task {


Task({this.isDone,this.name,this.time,this.priorityValue});
  final String name;
   bool isDone;
   final DateTime time;
   int priorityValue;



 factory Task.fromJson(Map<String, dynamic> jsonData) {
    return Task(
      name: jsonData['name'],
      isDone: false,
      time: jsonData['time'],
      priorityValue: jsonData['priorityValue'],
    );
  }

  toJSONEncodable() {
    Map<String, dynamic> m = new Map();

    m['name'] = name;
    m['isDone'] = isDone;
    m['time'] = time;
    m['priorityValue'] = priorityValue;

    return m;
  }

  static Map<String, dynamic> toMap(Task task) => {
        'name': task.name,
        'isDone': task.isDone,
        'time': task.time,
        'priorityValue': task.priorityValue,
      };
}

当使用 localStorage 包保存一些对象列表时,我得到了这个错误 =>

(Flutter)未处理的异常:将对象转换为可编码对象失败:“DateTime”实例

_saveToStorage() {
storage.setItem('tasks', list.toJSONEncodable());
print("Saved");

}

我尝试使用 .toString() 但后来我收到此错误 => type 'String' is not a subtype of type 'int' of 'index'

有什么想法可以在 LocalStorage 包上保存日期时间吗?

更新:

factory Task.fromJson(Map<String, dynamic> jsonData) {
return Task(
  name: jsonData['name'],
  isDone: false,
  time: jsonData["time"] == null ? null : DateTime.parse(jsonData["time"]),
  priorityValue: jsonData['priorityValue'],
);


 }

  toJSONEncodable() {
Map<String, dynamic> m = new Map();

m['name'] = name;
m['isDone'] = isDone;
m['time'] = time == null ? null : time.toIso8601String();
m['priorityValue'] = priorityValue;

return m;


 }

static Map<String, dynamic> toMap(Task task) => {
    'name': task.name,
    'isDone': task.isDone,
    'time': task.time,
    'priorityValue': task.priorityValue,
  };


var items = storage.getItem('tasks');
            if (items != null) {
              list.items = List<Task>.from(
                (items as List).map(
                  (item) => Task(
                    name: item['name'],
                    isDone: item['isDone'],
                    time: DateTime.parse(item['time']),
                    priorityValue: items['priorityValue'],
                  ),
                ),
              );
            }

更新后我收到此错误“类型'String'不是'index'类型'int'的子类型”

更新2:

var items = storage.getItem('tasks');

            if (items != null) {
              final decodedJson = jsonDecode(items);
              list.items = (decodedJson as List)
                  .map((e) => Task.fromJson(e))
                  .toList();
              final task = list.items.first;
              print("${task.name}");
              // list.items = List<Task>.from(
              //   (items as List).map(
              //     (item) => Task(
              //       name: item['name'],
              //       isDone: item['isDone'],
              //       time: DateTime.parse(item['time']),
              //       priorityValue: items['priorityValue'],
              //     ),
              //   ),
              // );
            }

第二次更新后,我得到“类型 '_InternalLinkedHashMap' 不是类型 'String' 的子类型”

已修复

我将模型中的 DaeTme 更改为字符串,并在获取时将时间转换为字符串

"${selectedDate.toLocal()}".split(' ')[0]

【问题讨论】:

    标签: flutter dart


    【解决方案1】:

    我强烈建议您使用 Retrofitjson_serializable 来描述您的 API

    它可能看起来像这样:

    import 'package:json_annotation/json_annotation.dart';
    
    part 'task.g.dart';
    
    @JsonSerializable(nullable: false, explicitToJson: true)
    class Task {
      final String name;
      bool isDone;
      final DateTime time;
      int priorityValue;
    
      Task({this.isDone, this.name, this.time, this.priorityValue});
    
      factory Task.fromJson(Map<String, dynamic> json) => _$TaskFromJson(json);
    
      Map<String, dynamic> toJson() => _$TaskToJson(this);
    }
    

    之后你需要运行build_runner
    flutter pub run build_runner build

    它会毫无痛苦地为您生成toJsonfromJson 方法:

    Task _$TaskFromJson(Map<String, dynamic> json) {
      return Task(
        isDone: json['isDone'] as bool,
        name: json['name'] as String,
        time: DateTime.parse(json['time'] as String),
        priorityValue: json['priorityValue'] as int,
      );
    }
    
    Map<String, dynamic> _$TaskToJson(Task instance) => <String, dynamic>{
          'name': instance.name,
          'isDone': instance.isDone,
          'time': instance.time.toIso8601String(),
          'priorityValue': instance.priorityValue,
        };
    

    您可以查看测试:

    void main() {
      test('Task should be parsed from json', () {
        const json = '''
        [
          {
            "name": "testing",
            "isDone": false,
            "time": "2021-01-12T13:57:10.705476",
            "priorityValue": 0
          }
        ]
        ''';
    
        final List decodedJson = jsonDecode(json);
        final List<Task> list = decodedJson.map((e) => Task.fromJson(e)).toList();
    
        final Task task = list.first;
    
        expect(task.name, 'testing');
        expect(task.isDone, false);
        expect(task.time, DateTime.parse("2021-01-12T13:57:10.705476"));
        expect(task.priorityValue, 0);
      });
    }
    

    【讨论】:

    • var items = storage.getItem('tasks');打印(“$项目”); I/flutter (8537): [{name: testing, isDone: false, time: 2021-01-12T13:57:10.705476, priorityValue: 0}]
    • String 类型的时间变量所以我添加了时间:DateTime.parse(item['time']), type 'String' is not a subtype of type 'int' of 'index' 会出现
    • 再次检查您尝试传递给fromJson 方法的内容,同时检查类型是什么
    【解决方案2】:

    使用 toJson

    "changeDate": changeDate == null ? null : changeDate.toIso8601String(),

    和来自Json

    changeDate: json["changeDate"] == null ? null : DateTime.parse(json["changeDate"]),

    【讨论】:

    • 我在 from JSON DateTime.parse(jsonData['time']) 和 JSON m['time'] = time.toIso8601String();现在我得到这个错误类型'String'不是'DateTime'类型的子类型
    • 我添加了一个 morre 代码 var items = storage.getItem('tasks'); if (items != null) { list.items = List.from( (items as List).map( (item) => Task( name: item['name'], isDone: item['isDone' ], time: DateTime.parse(item['time']), priorityValue: items['priorityValue'], ), ), ); } 现在获取类型 'String' 不是 'index' 类型 'int' 的子类型
    • 'String' 不是 'DateTime' 类型的子类型看起来像 fromJson 的问题,但你的 sn-p 看起来不错。也许您可以将代码更新到您的问题中。 'String' 类型不是 'index' 类型的 'int' 类型的子类型,这意味着您错误地将地图索引用于列表 -> 所以 myVar['time'] 而不是 myVar[1]
    • 上面的 toJson 代码可以进一步简化为:"changeDate": changeDate?.toIso8601String(),。见prefer_null_aware_operators
    猜你喜欢
    • 2021-10-05
    • 2021-04-08
    • 2021-05-05
    • 2019-11-06
    • 2020-07-18
    • 2021-11-04
    • 2020-08-21
    • 2023-04-09
    • 1970-01-01
    相关资源
    最近更新 更多