Json Serializable - Invalid argument(s) (input): Must not be null - json

I am trying to set JSON values in My Model Class. But its returning error as Invalid argument(s) (input): Must not be null
UserAccount.dart
import 'package:json_annotation/json_annotation.dart';
part 'userAccount.g.dart';
#JsonSerializable(nullable: true,disallowUnrecognizedKeys:true,includeIfNull:true)
class UserAccount{
String id;
String name;
String email;
String profile_pic;
String country;
String phoneNumber;
bool isNewUser;
int role;
int account_status;
String token;
DateTime token_expiry;
String facebook_profile_url;
String google_profile_url;
String twitter_profile_url;
int matchStixx_count;
DateTime created_at;
DateTime updated_at;
UserAccount({
this.id,
this.name,
this.email,
this.profile_pic,
this.country,
this.phoneNumber,
this.isNewUser,
this.role,
this.account_status,
this.token,
this.token_expiry,
this.facebook_profile_url,
this.google_profile_url,
this.twitter_profile_url,
this.matchStixx_count,
this.created_at,
this.updated_at
});
factory UserAccount.fromJson(Map<String,dynamic> json) => _$UserAccountFromJson(json);
Map<String,dynamic> toJson() =>_$UserAccountToJson(this);
}
UserAccount.g.dart
part of 'userAccount.dart';
UserAccount _$UserAccountFromJson(Map<String, dynamic> json) {
return UserAccount(
id: json['_id'] as String,
name: json['name'] as String,
email: json['email'] as String,
profile_pic: json['profile_pic'] as String,
country: json['country'] as String,
phoneNumber: json['phoneNumber'] as String,
isNewUser: json['isNewUser'] as bool,
role: json['role'] as int,
account_status: json['account_status'] as int,
token: json['token'] as String,
token_expiry: DateTime.parse(json['token_expiry'] as String),
facebook_profile_url: json['facebook_profile_url'] as String,
google_profile_url: json['google_profile_url'] as String,
twitter_profile_url: json['twitter_profile_url'] as String,
matchStixx_count: json['matchStixx_count'] as int,
created_at: DateTime.parse(json['created_at'] as String),
updated_at: DateTime.parse(json['updated_at'] as String)
);
}
Map<String, dynamic> _$UserAccountToJson(UserAccount instance) =>
<String, dynamic>{
'id': instance.id,
'name': instance.name,
'email': instance.email,
'profile_pic': instance.profile_pic,
'country': instance.country,
'phoneNumber': instance.phoneNumber,
'isNewUser': instance.isNewUser,
'role': instance.role,
'account_status': instance.account_status,
'token': instance.token,
'token_expiry': instance.token_expiry,
'facebook_profile_url': instance.facebook_profile_url,
'google_profile_url': instance.google_profile_url,
'twitter_profile_url': instance.twitter_profile_url,
'matchStixx_count': instance.matchStixx_count,
'created_at': instance.created_at,
'updated_at': instance.updated_at,
};
JSON Data - this JSON is stored in ( responseBody["userData"] )
{_id: 1, name:some name, email: someName#domain.com, profile_pic:
https://xyz/yzz.png, isNewUser: true, role: 1, account_status: 1,
matchStixx_count: 20, created_at: 2020-05-15T06:41:24.528Z, __v: 0}
Init Of Model
userAccount = new UserAccount.fromJson(responseBody["userData"]); //geting error here

It would have been much easier if you posted the full stacktrace since it contains the information about which field are null:
Unhandled exception:
Invalid argument(s) (input): Must not be null
#0 _RegExp.firstMatch (dart:core-patch/regexp_patch.dart:222:24)
#1 DateTime.parse (dart:core/date_time.dart:282:22)
#2 _$UserAccountFromJson (file:///stackoverflow.dart:64:30)
#3 new UserAccount.fromJson (file:///stackoverflow.dart:47:7)
#4 main (file:///stackoverflow.dart:5:15)
#5 _startIsolate.<anonymous closure> (dart:isolate-patch/isolate_patch.dart:301:19)
#6 _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:168:12)
The problematic line in the code the following:
token_expiry: DateTime.parse(json['token_expiry'] as String),
Since your json does not contain token_expiry then the result here will be null. But since DateTime.parse does not accept null as input your get the error "Must not be null".
For a fix you could change the line to something like this:
token_expiry: json['token_expiry'] == null ? null : DateTime.parse(json['token_expiry'] as String),
Which will then give the same error for the field updated_at so you should properly also do:
created_at: json['created_at'] == null ? null : DateTime.parse(json['created_at'] as String),
updated_at: json['updated_at'] == null ? null : DateTime.parse(json['updated_at'] as String));

If anyone passing by and had the same issue you need to verify your variable names like if you have a Map<String, dynamic> then you need to verify the key name that's what happens to me hope this helps good luck

Related

Wrong return type from json_serializable?

I have a Dio service that is returning some json:
final response = await di<Api>().dio.get('Measurement');
final List<InspectionResponse> ret = response.data.map((e) => InspectionResponse.fromJson(e)).toList();
My json look like this:
[
{
id: a7fa071d-d518-4c65-8dd1-4c0a04939f45,
blobName: d19e5f92-f326-437f-8e72-72268def65ec_42a4c288-ee16-4332-91eb-d961201c086d,
description: null,
measurementType: 1,
state: 3,
score: 0.32693514227867126,
tagName: Grit-Fine,
createdAt: 2022-09-02T12: 43: 48.582Z
},
{
id: a7fa071d-d518-4c65-8dd1-4c0a04939f46,
blobName: d19e5f92-f326-437f-8e72-72268def65ec_42a4c288-ee16-4332-91eb-d961201c086d,
description: null,
measurementType: 1,
state: 3,
score: 0.32693514227867126,
tagName: Grit-Fine,
createdAt: 2022-09-02T12: 43: 48.582Z
}
]
My model is this:
#JsonSerializable()
class InspectionResponse {
final String id;
final String blobName;
final int state;
final int measurementType;
final double score;
final String tagName;
final DateTime createdAt;
final String? description;
InspectionResponse(this.id, this.blobName, this.state, this.measurementType,
this.score, this.tagName, this.createdAt, this.description);
factory InspectionResponse.fromJson(Map<String, dynamic> json) =>
_$InspectionResponseFromJson(json);
Map<String, dynamic> toJson() => _$InspectionResponseToJson(this);
}
And the genetated _$InspectionResponseFromJson:
InspectionResponse _$InspectionResponseFromJson(Map<String, dynamic> json) =>
InspectionResponse(
json['id'] as String,
json['blobName'] as String,
json['state'] as int,
json['measurementType'] as int,
(json['score'] as num).toDouble(),
json['tagName'] as String,
DateTime.parse(json['createdAt'] as String),
json['description'] as String?,
);
The line:
final List<InspectionResponse> ret = response.data.map((e) => InspectionResponse.fromJson(e)).toList();
Give me this error:
Unhandled Exception: type 'List<dynamic>' is not a subtype of type 'List<InspectionResponse>'
But I do not understand this? The .map function convert the List<dynamic> to List<InspectionResponse> I would think, as the InspectionResponse.fromJson(e) returns a InspectionResponse, right? So what am I missing here?
This should work:
final List<InspectionResponse> ret = response.data.map<InspectionResponse>((e) => InspectionResponse.fromJson(e)).toList();

How to solve: The argument type 'dynamic' can't be assigned to the parameter type 'Iterable<dynamic>'

I always get the error The argument type 'dynamic' cannot be assigned to the parameter type 'Iterable' for the line json["geraete"].map((x) => RDevice.fromJson(x)), can someone help me?
factory Reservation.fromJson(Map<String, dynamic> json) => Reservation(*emphasized text*
resNr: json['resNr'] as int,
vbid: json['vbid'] as int,
benutzer: json['benutzer'] as String,
geraete: List<RDevice>.from(**json["geraete"].map((x) => RDevice.fromJson(x))**),
von: json['von'] as String,
bis: json['bis'] as String,
abgabe: json['abgabe'] as String,
abholung: json['abholung'] as String,
rdatum: json['rdatum'] as String,
status: json['status'] as String,
startTime: json['startTime'] as int, // slot nummer
endTime: json['endTime'] as int,
);
Here is the part from my RDevice class
factory RDevice.fromJson(Map<String, dynamic> json) => RDevice(
id: json['id'] as int,
resid: json['resid'] as int,
deviceid: json['geraetid'] as int,
description: json['bezeichnung'] as String,
);
Try to change it to
geraete: List<RDevice>.from((json["geraete"] as List<Map<String, dynamic>>).map((x) => RDevice.fromJson(x))),

Flutter: Decoding List<dynamic> to List<String> silently failing

When casting from a Json list object to a list String, instead of failing to cast, the process silently fails without any warnings or errors to identify what is going wrong.
Steps to Reproduce
Take the below factory and model:
class Topic {
int? id;
String name;
String displayName;
int? parentId;
List<String>? contentThemes;
List<String>? channels;
Topic({this.id, required this.name, required this.displayName, this.parentId, this.contentThemes, this.channels});
factory Topic.fromJson(Map<String, dynamic> json) {
var topic = Topic(
id: json['id'] as int?,
name: json['name'] as String,
displayName: json['displayName'] as String,
parentId: json['parentId'] as int?,
contentThemes: json['contentThemes'] as List<String>?,
channels: json['channels'] as List<String>?,
);
return topic;
}
}
Expected results:
The expectation is that flutter is able to identify that json['contentThemes'] is not a complex object and cast it from List dynamic to List String
OR if it is unable to, it should throw an error to the developer to highlight the failure to cast.
Actual results:
When trying to cast List to List (contentThemes, channels) it stops execution and silently fails to complete the task so the data is never returned.
The work around currently is to treat this as a complex object and do something like this:
class Topic {
int? id;
String name;
String displayName;
int? parentId;
List<String>? contentThemes;
List<String>? channels;
Topic({this.id, required this.name, required this.displayName, this.parentId, this.contentThemes, this.channels});
factory Topic.fromJson(Map<String, dynamic> json) {
var topic = Topic(
id: json['id'] as int?,
name: json['name'] as String,
displayName: json['displayName'] as String,
parentId: json['parentId'] as int?,
contentThemes: (json['channels'] as List?)?.map((item) => item as String)?.toList(),
channels: (json['contentThemes'] as List?)?.map((item) => item as String)?.toList()
);
return topic;
}
}
Hope this helps anyone else as this was a tricky issue to debug due to the way flutter currently handles this.
Try this:
channels: List<String>.from(json['contentThemes'].map((x) => x))

Error: Expected a value of type 'String', but got one of type 'Null'

I am learing about api's and http request in flutter and I got an error in making a get request
I got this error : Error: Expected a value of type 'String', but got one of type 'Null'
enter image description here
I got this error:
enter image description here
When you say data[id] as String for example, that means: data[id] is null.
factory Formule.fromMap(Map? data) {
if (data == null) {
return const Formule(
id: '', title: '', prix: 0, nombreDePlace: 0, alertThreshold: 0, remainingPlaces: 0);
}
return Formule(
id: data['id'] as String,
title: data['title'] as String,
prix: data['prix'] as double,
nombreDePlace: data['nombreDePlace'] as int,
alertThreshold: data['alertThreshold'] as int,
remainingPlaces: data['remainingPlaces'] as int);
}
2 solutions:
id: data['id'] as String?,
Or
id: data['id'] as String? ?? "",

type '_InternalLinkedHashMap<String, dynamic>' is not a subtype of type 'String' JSON Mapinng into model

hello everyone I'm trying to fetch JSON from API, but I'm getting this error while mapping the JSON into the model I created it type '_InternalLinkedHashMap<String, dynamic>' is not a subtype of type 'String'
this is the JSON response
{"data":{"userinfo":[{"firstname":"MAEN","lastname":"NASSAN","email":"maen.alnassan#outlook.com","active_status":0,"dark_mode":0,"messenger_color":"#2180f3","avatar":"avatar.png","gender":"male","region":"Turkey","birthyear":"2021","birthday":"1","birthmonth":"January","phonenumber":53105311,"category":"0","profilestatus":"private","ban":"0","banReason":"0","banDurationByDays":"0","email_verified_at":null,"created_at":"2021-05-24T16:27:52.000000Z","updated_at":"2021-05-24T16:27:52.000000Z"}],"userfriendsPosts":[{"postid":1,"userid":3,"posttitle":"Post 1 mohamed","post":"noattachment","likesCounter":0,"commentsCounter":0,"category":"0","created_at":"2021-05-22T20:49:48.000000Z","updated_at":"2021-05-22T20:49:48.000000Z"},{"postid":3,"userid":3,"posttitle":"Post 2 mohamed","post":"noattachment","likesCounter":0,"commentsCounter":0,"category":"0","created_at":"2021-05-22T20:58:40.000000Z","updated_at":"2021-05-22T20:58:40.000000Z"},{"postid":4,"userid":3,"posttitle":"Post 3 mohamed","post":"noattachment","likesCounter":0,"commentsCounter":0,"category":"0","created_at":"2021-05-22T20:58:43.000000Z","updated_at":"2021-05-22T20:58:43.000000Z"}],"usernotifications":[],"userlikes":[]}}
and this is the Model Class
import 'dart:convert';
Data dataFromJson(String str) => Data.fromJson(json.decode(str));
String dataToJson(Data data) => json.encode(data.toJson());
class Data {
Data({
this.data,
});
DataClass data;
factory Data.fromJson(Map<String, dynamic> json) => Data(
data: DataClass.fromJson(json["data"]),
);
Map<String, dynamic> toJson() => {
"data": data.toJson(),
};
}
class DataClass {
DataClass({
this.userinfo,
this.userfriendsPosts,
this.usernotifications,
this.userlikes,
});
List<Userinfo> userinfo;
List<UserfriendsPost> userfriendsPosts;
List<dynamic> usernotifications;
List<dynamic> userlikes;
factory DataClass.fromJson(Map<String, dynamic> json) => DataClass(
userinfo: List<Userinfo>.from(json["userinfo"].map((x) => Userinfo.fromJson(x))),
userfriendsPosts: List<UserfriendsPost>.from(json["userfriendsPosts"].map((x) => UserfriendsPost.fromJson(x))),
usernotifications: List<dynamic>.from(json["usernotifications"].map((x) => x)),
userlikes: List<dynamic>.from(json["userlikes"].map((x) => x)),
);
Map<String, dynamic> toJson() => {
"userinfo": List<dynamic>.from(userinfo.map((x) => x.toJson())),
"userfriendsPosts": List<dynamic>.from(userfriendsPosts.map((x) => x.toJson())),
"usernotifications": List<dynamic>.from(usernotifications.map((x) => x)),
"userlikes": List<dynamic>.from(userlikes.map((x) => x)),
};
}
class UserfriendsPost {
UserfriendsPost({
this.postid,
this.userid,
this.posttitle,
this.post,
this.likesCounter,
this.commentsCounter,
this.category,
this.createdAt,
this.updatedAt,
});
int postid;
int userid;
String posttitle;
String post;
int likesCounter;
int commentsCounter;
String category;
DateTime createdAt;
DateTime updatedAt;
factory UserfriendsPost.fromJson(Map<String, dynamic> json) => UserfriendsPost(
postid: json["postid"],
userid: json["userid"],
posttitle: json["posttitle"],
post: json["post"],
likesCounter: json["likesCounter"],
commentsCounter: json["commentsCounter"],
category: json["category"],
createdAt: DateTime.parse(json["created_at"]),
updatedAt: DateTime.parse(json["updated_at"]),
);
Map<String, dynamic> toJson() => {
"postid": postid,
"userid": userid,
"posttitle": posttitle,
"post": post,
"likesCounter": likesCounter,
"commentsCounter": commentsCounter,
"category": category,
"created_at": createdAt.toIso8601String(),
"updated_at": updatedAt.toIso8601String(),
};
}
class Userinfo {
Userinfo({
this.firstname,
this.lastname,
this.email,
this.activeStatus,
this.darkMode,
this.messengerColor,
this.avatar,
this.gender,
this.region,
this.birthyear,
this.birthday,
this.birthmonth,
this.phonenumber,
this.category,
this.profilestatus,
this.ban,
this.banReason,
this.banDurationByDays,
this.emailVerifiedAt,
this.createdAt,
this.updatedAt,
});
String firstname;
String lastname;
String email;
int activeStatus;
int darkMode;
String messengerColor;
String avatar;
String gender;
String region;
String birthyear;
String birthday;
String birthmonth;
int phonenumber;
String category;
String profilestatus;
String ban;
String banReason;
String banDurationByDays;
dynamic emailVerifiedAt;
DateTime createdAt;
DateTime updatedAt;
factory Userinfo.fromJson(Map<String, dynamic> json) => Userinfo(
firstname: json["firstname"],
lastname: json["lastname"],
email: json["email"],
activeStatus: json["active_status"],
darkMode: json["dark_mode"],
messengerColor: json["messenger_color"],
avatar: json["avatar"],
gender: json["gender"],
region: json["region"],
birthyear: json["birthyear"],
birthday: json["birthday"],
birthmonth: json["birthmonth"],
phonenumber: json["phonenumber"],
category: json["category"],
profilestatus: json["profilestatus"],
ban: json["ban"],
banReason: json["banReason"],
banDurationByDays: json["banDurationByDays"],
emailVerifiedAt: json["email_verified_at"],
createdAt: DateTime.parse(json["created_at"]),
updatedAt: DateTime.parse(json["updated_at"]),
);
Map<String, dynamic> toJson() => {
"firstname": firstname,
"lastname": lastname,
"email": email,
"active_status": activeStatus,
"dark_mode": darkMode,
"messenger_color": messengerColor,
"avatar": avatar,
"gender": gender,
"region": region,
"birthyear": birthyear,
"birthday": birthday,
"birthmonth": birthmonth,
"phonenumber": phonenumber,
"category": category,
"profilestatus": profilestatus,
"ban": ban,
"banReason": banReason,
"banDurationByDays": banDurationByDays,
"email_verified_at": emailVerifiedAt,
"created_at": createdAt.toIso8601String(),
"updated_at": updatedAt.toIso8601String(),
};
}
and this is the API request function
static Future<List<Data>> getData(token) async{
Dio dio = new Dio();
dio.options.headers["Authorization"] = "bearer $token";
dio.options.headers["Content-Type"] = 'application/json';
dio.options.headers["Accept"] = 'application/json';
await dio.get(url,).then((response) {
final List<Data> _data = dataFromJson(response.data) as List<Data>;
return _data;
}
).catchError((error) => print(error));
}
I tried all the method to fetch the data and the complex JSON List but it's always ending withe errors looks like this errors
The error you're getting is telling you: "your code expects a String, but you gave it a _InternalLinkedHashMap<String, dynamic> (i.e. a Map<String, dynamic>)".
It's not clear where the error is happening, but my guess is that response.data is a Map<String, dynamic>, but dataFromJson expects a String, and this line is causing the error.
If you look at the docs for Dio.get() (https://pub.dev/documentation/dio/latest/dio/Dio/get.html),
you can see the signature is:
Future<Response<T>> get<T>(String path, { ... });
When you call dio.get(url) without passing a type parameter, it defaults to dynamic, which essentially turns off type-checking. If you expect your api to return a String, you can provide that to dio by using: dio.get<String>(url).
However, if you're immediately going to jsonDecode it, you could modify dataFromJson to accept a Map<String, dynamic> rather than a String, and skip the jsonDecode step.
Finally, I'd recommend you to check out a json library (json_serializable is very easy to get started with). Hand writing json serialization code is repetitive and error-prone. Instead of manually writing your toJson() and fromJson() functions, you simply define stubs, and you can generate serialization code at compile time.
https://pub.dev/packages/json_serializable