Reputation: 901
I am trying to convert the object "Week" to json.
https://flutter.dev/docs/development/data-and-backend/json this is the source that i used
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,
};
}
I used this:
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);
But the problem is that I get this result:
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)
Upvotes: 48
Views: 89695
Reputation: 1175
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-projects
becomes:
//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);
}
Freezed: https://pub.dev/packages/freezed
Don't forget to edit pubspec.yaml
for freezed
and freezed_annotation
Upvotes: 0
Reputation: 8365
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:
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.
Upvotes: 61
Reputation: 901
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":""}
Upvotes: 26