Reputation: 132
I have worked on decoding/encoding JSONs in my Flutter/Dart app. The decoding works just fine, but I have a very nasty problem when encoding my objects to JSON.
These are nested objects. Every one of them has its toJson and fromJson methods, in order to ensure that jsonEncode and Decode works. A small snippet of my work:
class App {
factory App.fromJson(Map<String, dynamic> json) => App(
langPref: json["langPref"],
langFallb: json["langFallb"],
users: List.of(json["users"]).map((i) => i).toList(),
);
String langPref;
String langFallb;
List<User> users;
/// JSON-Export
Map<String, dynamic> toJson() => {
"langPref": langPref,
"langFallb": langFallb,
"users": jsonEncode(users),
};
}
and the nested class:
class User {
int userid;
// actually there's more, including more nested objects
/// JSON-Import
factory User.fromJson(Map<String, dynamic> json) {
return User(
userid: int.parse(json["userid"]),
);
}
/// JSON-Export
Map<String, dynamic> toJson() {
return {
"userid": this.userid,
};
}
}
The problem is: When I encode the top level class "App", it correctly calls the toJson() method of the nested class. However, the corresponding JSON should read like this:
{
"langPref":"de-DE",
"langFallb":"en-GB",
"users":
[
{
"userid": 1
// and so on
It does, however, look like this:
{
"langPref":"de-DE",
"langFallb":"en-GB",
"users":"[{\"userid\":1
// and so on
So, the jsonEncode somehow introduces additional double quotes, which even makes sense somehow. It produces a String, and inside the JSON a string should be encoded .... But I guuess I'm just doing something wrong and missing something obvious .... How can I tell jsonEncode to accept the result of the operation, instead of encoding it as a string?
Can somebody help me?
Upvotes: 0
Views: 1886
Reputation: 937
This problem rises because you use jsonEncode()
which return string object
you must use jsonDecode()
that return a Map<String, dynamic>
and your App class will be like following
class App {
factory App.fromJson(Map<String, dynamic> json) => App(
langPref: json["langPref"],
langFallb: json["langFallb"],
users: List.of(json["users"]).map((i) => i).toList(),
);
String langPref;
String langFallb;
List<User> users;
/// JSON-Export
Map<String, dynamic> toJson() => {
"langPref": langPref,
"langFallb": langFallb,
"users": jsonEDecode(users),
};
}
Update
2nd method is to remove jsonEncode()
without use jsonDecode()
3rd method use tojson()
method in user class like following code
"users": users.map((user) => user.tojson()).toList(),
4th method the best method use json_serializable library with json_annotation library to generate json serialization for annotated classes, Flutter team approve this method as the best and the official one as described in Official Flutter Documentation.
app.dart
import 'package:json_annotation/json_annotation.dart';
part 'app.g.dart';
@JsonSerializable()
class App{
String langPref;
String langFallb;
List<User> users;
App({this.langPref, this.langFallb, this.users});
factory App.fromJson(Map<String, dynamic> json) => _$AppFromJson(json);
Map<String, dynamic> toJson() => _$AppToJson(this);
}
user.dart
import 'package:json_annotation/json_annotation.dart';
part 'user.g.dart';
@JsonSerializable()
class User{
int userId;
User({this.userId});
factory User.fromJson(Map<String, dynamic> json) => _$UserFromJson(json);
Map<String, dynamic> toJson() => _$UserToJson(this);
}
Upvotes: 1
Reputation: 132
Great .... I will answer my own question. :-)
Further experiments lead to the following conclusion:
class App {
factory App.fromJson(Map<String, dynamic> json) => App(
langPref: json["langPref"],
langFallb: json["langFallb"],
users: List.of(json["users"]).map((i) => i).toList(),
);
String langPref;
String langFallb;
List<User> users;
/// JSON-Export
Map<String, dynamic> toJson() => {
"langPref": langPref,
"langFallb": langFallb,
"users": users,
};
}
New is only the last line .... I can directly pass the users list. It's not necessary to use jsonEncode for all of the nested objects and lists and maps etc.
Sorry for stealing the time of the readers, but maybe this answer will help others.
Upvotes: 0