如何在 Flutter 中将对象编码为 json



我正在尝试将对象"Week"转换为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)

jsonEncode 需要一个Map<String, dynamic>,而不是一个Week对象。调用toJson()方法应该可以解决问题。

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

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

要回答您的具体问题:

  1. 因为dart不是javascript/打字稿。Dart 在运行时检查类型,因此您必须明确告诉它如何转换事物 - Dart 中也没有反射,因此它无法自行弄清楚。
  2. 您可以使用使用代码生成的库自动为您执行这些操作 - 尽管在运行时仍然无法实现 - 阅读有关 JSON 序列化的更多信息。
  3. 最简单的方法是直接在类中实现方法,因为这是您可以在根对象中访问的位置。请记住,jsonEncode需要的结构是Map<String, dynamic>,但dynamic部分实际上意味着List<dynamic>Map<String, dynamic>或与json兼容的原语,例如Stringdouble- 如果你试着想象这种嵌套结构的这种类型是什么样子的,你会意识到它基本上是json。因此,当你做类似'goalList': _goalList,的事情时,你给它一个对象,这不是允许的类型之一。

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

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

为了使我的代码正常工作,我还需要在类Goal中实现toJson()方法(因为我在Week中使用了List<Goal>)。

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

此外,我需要向DateTime对象添加.toIso8601String(),就像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":""}

从上面 @Phillip 的 Json 序列化答案中获取建议 2,我相信您可以跳过@JsonSerializable注释并只使用@Freezed注释,因为 Freezed"将自动要求json_serializable从 Json/toJson 生成所有必要的内容。 所以这里的例子: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 不要忘记编辑pubspec.yaml以进行freezedfreezed_annotation

最新更新