Reputation: 4391
Am trying to access a model from inside it is parents model , so I get this error :
Unhandled Exception: Cyclic error in JSON stringify
Here is my code :
class User {
bool? success;
String? message;
String? token;
Data? data;
User({this.success, this.message, this.token, this.data});
User.fromJson(Map<String, dynamic> json) {
success = json['success'];
message = json['message'];
token = json['token'];
data = json['data'] != null ? Data.fromJson(json['data']) : null;
}
Map<String, dynamic> toJson() {
final data = <String, dynamic>{};
data['success'] = success;
data['message'] = message;
data['token'] = token;
data['data'] = data; //Here is the problem
return data;
}
}
class Data {
int? id;
int? mainUser;
String? deviceToken;
String? name;
bool? isLogged;
int? activationCode;
String? mobileNumber;
bool? isVerified;
bool? isActive;
int? code;
Data(
{this.id,
this.mainUser,
this.deviceToken,
this.name,
this.isLogged,
this.activationCode,
this.mobileNumber,
this.isVerified,
this.isActive,
this.code});
Data.fromJson(Map<String, dynamic> json) {
id = json['id'];
mainUser = json['main_user'];
deviceToken = json['device_token'];
name = json['name'];
isLogged = json['is_logged'];
activationCode = json['activation_code'];
mobileNumber = json['mobile_number'];
isVerified = json['is_verified'];
isActive = json['is_active'];
code = json['code'];
}
Map<String, dynamic> toJson() {
final data = <String, dynamic>{};
data['id'] = id;
data['main_user'] = mainUser;
data['device_token'] = deviceToken;
data['name'] = name;
data['is_logged'] = isLogged;
data['activation_code'] = activationCode;
data['mobile_number'] = mobileNumber;
data['is_verified'] = isVerified;
data['is_active'] = isActive;
data['code'] = code;
return data;
}
}
Upvotes: 3
Views: 866
Reputation: 31219
Your problem is related to scoping rules and what variable we are referring to when we use the name of a variable. When you are using a variable name, Dart will try and find a variable with that name starting from the scope you are in. If Dart don't find any variable with that name, it will search in a broader level of scope:
// Scope Level 0 (global scope)
class User {
// Scope Level 1 (class scope)
Data? data;
Map<String, dynamic> toJson() {
// Scope Level 2 (method scope)
final data = <String, dynamic>{};
data['data'] = data;
return data;
}
}
So when you are using data
in data['data'] = data
, Dart will start looking inside the scope of the method toJson()
. Here it finds the variable data
defined as final data = <String, dynamic>{}
and uses that without even looking at the variable inside your User
class.
The error you are getting is referring to the problem that your returned Map
contains a cyclic reference since it contains a reference to the map itself (data['data']
points to the map itself which then contains a data
key which contains the map with a data
key and so on...). The problem with this kind of Map
is that we cannot represent it with traditional JSON which makes Dart throw an exception since what you are trying to do cannot be achieve.
There are multiple solutions to this problem:
this.
to point to class variableIn situations where we want to refer to the class variable instead of a same-named method variable, we can prefix the reference with this.
which tells Dart to look in the class scope for the variable:
Map<String, dynamic> toJson() {
final data = <String, dynamic>{};
data['success'] = success;
data['message'] = message;
data['token'] = token;
data['data'] = this.data;
return data;
}
Another solution would be to prevent the confusion by not, in this case, use a variable name in the toJson()
method which are also a class variable. E.g. we could rename data
to map
:
Map<String, dynamic> toJson() {
final map = <String, dynamic>{};
map['success'] = success;
map['message'] = message;
map['token'] = token;
map['data'] = data;
return map;
}
In Dart, we have a shorthand syntax for methods which are just going to return a value (=>
). We can use that to create a method which declare a Map
with the needed key-value pairs and then immediately return it:
Map<String, dynamic> toJson() => <String, dynamic>{
'success': success,
'message': message,
'token': token,
'data': data,
};
Upvotes: 4