【问题标题】:How to encode an object to json in Flutter如何在 Flutter 中将对象编码为 json
【发布时间】:2019-10-17 18:47:53
【问题描述】:

我正在尝试将对象“周”转换为 json。

https://flutter.dev/docs/development/data-and-backend/json这是我使用的来源

class Week{
  DateTime _startDate;
  DateTime _endDate;
  List<Goal> _goalList;
  String _improvement;

  Week(this._startDate, this._endDate){
    this._goalList = List<Goal>();
    this._improvement = "";
  }

  Week.fromJson(Map<String, dynamic> json)
    : _startDate =  json['startDate'],
      _endDate = json['endDate'],
      _goalList = json['goalList'],
      _improvement = json['improvement'];

  Map<String, dynamic> toJson() => 
  {
    'startDate': _startDate,
    'endDate': _endDate,
    'goalList': _goalList,
    'improvement': _improvement,
  };
}

我用过这个:

DateTime startDate = currentDate.subtract(new Duration(days:(weekday-1)));
DateTime endDate = currentDate.add(new Duration(days:(7-weekday)));

Week week = new Week(startDate, endDate);
var json = jsonEncode(week);

但问题是我得到了这个结果:

Unhandled Exception: Converting object to an encodable object failed: Instance of 'Week'
#0      _JsonStringifier.writeObject (dart:convert/json.dart:647:7)
#1      _JsonStringStringifier.printOn (dart:convert/json.dart:834:17)
#2      _JsonStringStringifier.stringify (dart:convert/json.dart:819:5)
#3      JsonEncoder.convert (dart:convert/json.dart:255:30)
#4      JsonCodec.encode (dart:convert/json.dart:166:45)
#5      jsonEncode (dart:convert/json.dart:80:10)

【问题讨论】:

    标签: json flutter dart


    【解决方案1】:

    jsonEncode 需要Map&lt;String, dynamic&gt;,而不是Week 对象。调用您的 toJson() 方法应该可以解决问题。

    var json = jsonEncode(week.toJson());
    

    但是,请记住,您的 toJson() 方法也不正确,因为 _goalList 和日期等内容仍然是对象,而不是地图或列表。您还需要在这些上实现 toJson 方法。

    回答您的具体问题:

    1. 因为 dart 不是 javascript / typescript。 Dart 在运行时检查类型,因此您必须明确告诉它如何转换 - 而且 dart 中没有反射,因此它无法自行解决。
    2. 您可以使用一个使用代码生成的库来自动为您完成这些事情 - 但在运行时仍然无法实现 - 阅读更多关于 JSON serialization 的信息。
    3. 最简单的方法是直接在类中实现方法,因为您可以在根对象中访问这些方法。请记住jsonEncode 需要的结构是Map&lt;String, dynamic&gt;,但dynamic 部分实际上意味着List&lt;dynamic&gt;Map&lt;String, dynamic&gt; 或与json 兼容的原语,例如Stringdouble - 如果你试着想象这种类型的嵌套结构看起来如何,你会意识到它基本上是 json。因此,当您执行 'goalList': _goalList, 之类的操作时,您是在给它一个对象,这不是允许的类型之一。

    希望这能把事情弄清楚一点。

    【讨论】:

    • 感谢您的快速响应。我现在有几个问题: 1. 为什么对象到 json 的转换这么复杂? 2.没有更简单的方法吗? 3. 我怎样才能实现那些toJson() 方法?我必须创建单独的类还是可以将它们实现到Week 类中?
    • 对象内部的对象呢??
    【解决方案2】:

    对于任何想知道的人:我得到了我的解决方案。

    为了使我的代码正常工作,我还需要在我的班级Goal 中实现toJson() 方法(因为我在Week 中使用了List&lt;Goal&gt;)。

    class Goal{
      String _text;
      bool _reached;
    
      Map<String, dynamic> toJson() =>
      {
        'text': _text,
        'reached': _reached,
      }; 
    }
    

    另外,我需要将.toIso8601String() 添加到DateTime 对象中,就像Week 类中的那样:

    Map<String, dynamic> toJson() => 
      {
        'startDate': _startDate.toIso8601String(),
        'endDate': _endDate.toIso8601String(),
        'goalList': _goalList,
        'improvement': _improvement,
      };
    

    现在的输出是:

     {"startDate":"2019-05-27T00:00:00.000Z","endDate":"2019-06-02T00:00:00.000Z","goalList":[],"improvement":""}
    

    【讨论】:

    • 向@Philip 大喊大叫,他解释得这么好!
    • 我有一个问题。您为周周编写构造函数的方式 Week(this._startDate, this._endDate){ this._goalList = List(); this._improvement = ""; } 你如何实例化这样的类?
    • 我的意思是你是如何给 _goalList 和 _improvement 赋值的?
    【解决方案3】:

    从上面@Phillip的回答中为Json序列化采取建议2,Freezed包我相信你可以跳过@JsonSerializable注解而只使用@Freezed注解因为Freezed“会自动要求json_serializable生成所有必要的fromJson/到杰​​森。” 所以这里的例子:https://flutter.dev/docs/development/data-and-backend/json#use-code-generation-for-medium-to-large-projects 变成:

    //import 'package:json_annotation/json_annotation.dart';
    import 'freezed_annotation/freezed_annotation.dart';
    
    /// This allows the `User` class to access private members in
    /// the generated file. The value for this is *.g.dart, where
    /// the star denotes the source file name.
    part 'user.g.dart';
    part 'user.freezed.dart';
    /// An annotation for the code generator to know that this class needs the
    /// JSON serialization logic to be generated.
    @freezed
    class User {
      User(this.name, this.email);
    
      String name;
      String email;
    
      /// A necessary factory constructor for creating a new User instance
      /// from a map. Pass the map to the generated `_$UserFromJson()` constructor.
      /// The constructor is named after the source class, in this case, User.
      factory User.fromJson(Map<String, dynamic> json) => _$UserFromJson(json);
    
      /// `toJson` is the convention for a class to declare support for serialization
      /// to JSON. The implementation simply calls the private, generated
      /// helper method `_$UserToJson`.
      Map<String, dynamic> toJson() => _$UserToJson(this);
    }
    

    冻结:https://pub.dev/packages/freezed 不要忘记为freezedfreezed_annotation 编辑pubspec.yaml

    【讨论】:

      猜你喜欢
      • 2021-04-21
      • 2012-06-10
      • 2021-04-20
      • 2023-04-02
      • 1970-01-01
      • 2014-08-18
      • 1970-01-01
      • 2020-11-23
      • 2019-03-30
      相关资源
      最近更新 更多