How to encode an object to json in Flutter How to encode an object to json in Flutter dart dart

How to encode an object to json in Flutter


jsonEncode requires a Map<String, dynamic>, not a Week object. Calling your toJson() method should do the trick.

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

However, keep in mind that your toJson() method is also incorrect, as things like _goalList and the dates are still objects, not Maps or Lists. You'll need to implement toJson methods on those as well.

To answer your specific questions:

  1. Because dart is not javascript / typescript. Dart checks types at runtime, therefore you have to explicitly tell it how to convert things - also there is no reflection in dart, so it can't figure it out by itself.
  2. You can use a library that uses code generation to do these things automatically for you - it still wont be possible at runtime though - read more about JSON serialization.
  3. The easiest way would be to implement the methods directly in the classes, as that's where you have access to in your root object. Keep in mind that the structure that jsonEncode needs is a Map<String, dynamic>, but the dynamic part really means List<dynamic>, Map<String, dynamic> or a primitive that is json compatible such as String or double - if you try to imagine how such a nested structure of said types looks, you'll realise that it's basically json. So when you do something like 'goalList': _goalList, you're giving it an object, which is not one of the allowed types.

Hope this clears things up a bit.


for anyone wondering: I got my solution.

To make my code work I needed to implement the toJson() methods at my class Goal as well (because I used List<Goal> in Week).

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

Also, I needed to add .toIso8601String() to the DateTime objects like that in the Week class:

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

Now the output is:

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


Taking suggestion 2 from @Phillip's answer above for Json serialization, the Freezed package I believe you can skip the @JsonSerializable annotation and just used the @Freezed annotation because Freezed "will automatically ask json_serializable to generate all the necessary fromJson/toJson."So the example here: https://flutter.dev/docs/development/data-and-backend/json#use-code-generation-for-medium-to-large-projectsbecomes:

//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.@freezedclass 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);}

Freezed: https://pub.dev/packages/freezedDon't forget to edit pubspec.yaml for freezed and freezed_annotation