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

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))

Related

How can i convert a JSON String to List<String> in flutter?

I`m trying to retrieve the content of a table from oracle apex to my flutter app with http.get method, and atribute the values to a class i created. Problem is that 3 of the atributes of this class need to be List, so, when i try to map it, it returns this error: [ERROR:flutter/lib/ui/ui_dart_state.cc(198)] Unhandled Exception: type 'String' is not a subtype of type 'List' in type cast.
this is the JSON:
{
"items": [
{
"id": "1",
"nome": "Feijão Tropeiro",
"id_dia_da_semana": "seg",
"id_categoria": "ga",
"url_da_imagem": "https://live.staticflickr.com/65535/52180505297_2c23a61620_q.jpg",
"ingredientes": "vários nadas"
}
],
and this is the class:
// ignore_for_file: public_member_api_docs, sort_constructors_first
import 'dart:convert';
class Meal {
final String id;
final String descricao;
final List<String> ingredients;
final List<String> idDiaSem;
final List<String> idCategory;
final String imageUrl;
const Meal({
required this.id,
required this.descricao,
required this.ingredients,
required this.idDiaSem,
required this.idCategory,
required this.imageUrl,
});
Map<String, dynamic> toMap() {
return <String, dynamic>{
'id': id,
'nome': descricao,
'ingredientes': ingredients,
'id_dia_da_semana': idDiaSem,
'id_categoria': idCategory,
'url_da_imagem': imageUrl,
};
}
factory Meal.fromMap(Map<String, dynamic> map) {
return Meal(
id: map['id'] as String,
descricao: map['nome'] as String,
ingredients: map['ingredientes'] as List<String>,
idDiaSem: map['id_dia_da_semana'] as List<String>,
idCategory: map['id_categoria'] as List<String>,
imageUrl: map['url_da_imagem'] as String,
);
}
String toJson() => json.encode(toMap());
factory Meal.fromJson(String source) =>
Meal.fromMap(json.decode(source) as Map<String, dynamic>);
}
can anyone help me please to fix this error? i`ve tried to convert it unsuccessfully
When you have a string you want to parse to a list, there should be a separator. For example, let's suppose this strings:
// The separator here is a comma with a space, like ', '
String str1 = 'ingredient1, ingredient2, bread, idunno, etc';
// The separator here is a simple space, ' '
String str2 = 'ingredient1 ingredient2 bread idunno etc';
Once you identified the separator in the string, you may want to use the string split method in dart, specifying the separator. For example:
// Separator is a simple comma with no spaces, ','
String str1 = 'ingredient1,ingredient2,bread,idunno,etc';
// Splits the string into array by the separator
List<String> strList = str1.split(',');
// strList = ['ingredient1', 'ingredient2', 'bread', 'idunno', 'etc'];
More information on the split dart method at https://api.dart.dev/stable/2.14.4/dart-core/String/split.html
EDIT: Example with your code, supposing the property ingredients is a string that represents an array of strings, separated with ",":
factory Meal.fromMap(Map<String, dynamic> map) {
return Meal(
id: map['id'] as String,
descricao: map['nome'] as String,
ingredients: (map['ingredientes'] as String).split(','),
// ...
You can't cast them to List<String> because they simply aren't a list. If you want them to be a List with a single element you could do this instead:
ingredients: [map['ingredientes'] as String],
idDiaSem: [map['id_dia_da_semana'] as String],
idCategory: [map['id_categoria'] as String],
or make sure the JSON has them as list like
{
"items": [
{
"id": "1",
"nome": "Feijão Tropeiro",
"id_dia_da_semana": ["seg"],
"id_categoria": ["ga"],
"url_da_imagem": "https://live.staticflickr.com/65535/52180505297_2c23a61620_q.jpg",
"ingredientes": ["vários nadas"]
}
],
try this:
static List<Meal> fromMap(Map<String, dynamic> map) {
List<Meal> result = [];
for(var item in map['items']){
result.add(Meal(
id: item['id'] as String,
descricao: item['nome'] as String,
ingredients: item['ingredientes'] as String,
idDiaSem: item['id_dia_da_semana'] as String,
idCategory: item['id_categoria'] as String,
imageUrl: item['url_da_imagem'] as String,
))
}
return result;
}

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();

fetch user data from server flutter

I'm following this tutorial from devs docs to fetch data from internet but I can't decode response to User object.
Since I'm using Postman to check API I can tell you that my request is successfully received and server responses me with 200 and a body full of data (name, id and token) but when I try to call fromJson method inside try-catch block to create User object it fails and this error is printed :
flutter: Response 200
flutter: type '_InternalLinkedHashMap<String, dynamic>' is not a subtype of type 'String'
This is my User class :
class User extends Equatable {
final String token;
final String name;
final String id;
const User({
required this.token,
required this.name,
required this.id,
});
static const User empty = User(token: "token", name: "name", id: "id");
Map<String, dynamic> toMap() {
return <String, String>{
'token': token,
'name': name,
'id': id,
};
}
factory User.fromMap(Map<String, dynamic> json) {
return User(
token: json['token'] ?? "token",
name: json['name'] ?? "name",
id: json['id'] ?? "id",
);
}
String toJson() => json.encode(toMap());
factory User.fromJson(Map<String, dynamic> jsonMap) => User.fromMap(jsonMap);
#override
String toString() {
return token + ' ' + name + ' ' + id + '\n';
}
#override
List<Object?> get props => [token, name, id];
}
UserCredentials that's just a wrapper for username and password :
class UserCredentials {
final String name;
final String email;
final String password;
UserCredentials(
{required this.name, required this.email, required this.password});
factory UserCredentials.fromJson(Map<String, dynamic> json) {
return UserCredentials(
name: json['name'] as String,
email: json['email'] as String,
password: json['password'] as String,
);
}
Map<String, String> toJsonRegistration() {
return {
"name": name,
"email": email,
"password": password,
};
}
Map<String, String> toJsonLogin() {
return {
"email": email,
"password": password,
};
}
#override
String toString() {
return name + " " + email + " " + password + '\n';
}
}
And this is my user_repository function used to get data from server :
Future<User> _login(UserCredentials user) async {
User? userFetched;
//print(user);
http.Response response = await http.post(
Uri.parse("http://link_to_repo"),
body: user.toJsonLogin(),
);
print("Inizio");
print((response.body));
print(jsonDecode(response.body));
print(User.fromJson(jsonDecode(response.body)));
print("fine");
if (response.statusCode == 200) {
print(response.statusCode);
try {
userFetched = User.fromJson(jsonDecode(response.body));
print(userFetched);
} catch (e) {
print(e);
}
print("End");
return userFetched!;
} else {
print("Login Failure from repository");
throw Exception("Email already taken");
}
}
As you seen above it's able to print "Response 200" but not to complete successfully the operation inside try-catch block.
Edit :
This is the response.body :
{"data" : {"token":"50|IUMNqKgc7Vffmz8elRd0MIZeSyuEgHL418KwQ0Jz","name":"test","id":1}}
And jsonDecode(response.body)) :
{data: {token: 50|IUMNqKgc7Vffmz8elRd0MIZeSyuEgHL418KwQ0Jz, name: test, id: 1}}
Solution :
This post is a little confusing but to be clear :
Clucera gave me the exact solution to fetch the data and create User object so I accepted its answers.
Josip Domazet's answer helped me fixing the error but he didn't solve the problem because I still couldn't create User data.
Looking at your code it looks like you are doing the following
User.fromJson(jsonDecode(response.body));
and from there you are creating the User instance with the following factory
factory User.fromMap(Map<String, dynamic> json) {
return User(
token: json['token'] ?? "token",
name: json['name'] ?? "name",
id: json['id'] ?? "id",
);
The issue is that your Json is contained in another json called "data" as your print response show
{data: {token: 50|IUMNqKgc7Vffmz8elRd0MIZeSyuEgHL418KwQ0Jz, name: test, id: 1}}
in this case you have two solution, either you nest the keys inside your constructor (don't suggest you this approach)
factory User.fromMap(Map<String, dynamic> json) {
return User(
token: json['data']['token'] ?? "token",
name: json['data']['name'] ?? "name",
id: json['data']['id'] ?? "id",
);
Or where you parse the json you can extract directly the data json (I suggest you this option)
User.fromJson(jsonDecode(response.body)['data']);
jsonDecode(response.body) will return a Map. However your constructor User.fromJson takes a String as argument. Decoding it once is enough and from then on your can work with the Map you already have. So no need to call jsonDecode again in fromJson, this should work fine:
factory User.fromJson(Map<String, dynamic> jsonMap) =>
User.fromMap(jsonMap);
If we look at your exception it tell us just that:
flutter: type '_InternalLinkedHashMap<String, dynamic>' is not a subtype of type 'String'
Your constructor expects a String but received a Map (_InternalLinkedHashMap).

Flutter/Dart - Parsing JSON to a model

I was wondering if anyone could help, please? I'm very new to Flutter/Dart here and I'm trying to parse a nested JSON response, into a model. I've used the "JSON to Dart" generator, which seems to have worked well, except when it is parsing "responses".
I suspect the issue is because the "responses" vary in results - sometimes it could be null, a single array, or multiple.
Running .runtimeType has shown me that it can return null if it's empty, List<dynamic> if there is only one array, and _InternalLinkedHashMap<String, dynamic> when there are multiple.
I have tried many different approaches to try and resolve this and looked through many different StackOverflow answers, but nothing seems to work. The error simply changes with every change I make.
Below is my code and my error.
The error:
_TypeError (type '(dynamic) => Null' is not a subtype of type '(String, dynamic) => void' of 'f')
The code:
class VideoComments {
int id;
String comment;
int uid;
int likes;
bool isLikedByUser;
String posterProfilePic;
String posterUsername;
List<Responses> responses;
VideoComments(
{this.id,
this.comment,
this.uid,
this.likes,
this.isLikedByUser,
this.posterProfilePic,
this.posterUsername,
this.responses});
VideoComments.fromJson(Map<String, dynamic> json) {
print("RESP: ${json['responses'].runtimeType}");
id = json['id'];
comment = json['comment'];
uid = json['uid'];
likes = json['likes'];
isLikedByUser = json['isLikedByUser'];
posterProfilePic = json['poster_profile_pic'];
posterUsername = json['poster_username'];
if (json['responses'] != null) {
List<Responses> responses = [];
json['responses'].forEach((v) {
responses.add(new Responses.fromJson(v));
});
}
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['id'] = this.id;
data['comment'] = this.comment;
data['uid'] = this.uid;
data['likes'] = this.likes;
data['isLikedByUser'] = this.isLikedByUser;
data['poster_profile_pic'] = this.posterProfilePic;
data['poster_username'] = this.posterUsername;
if (this.responses != null) {
data['responses'] = this.responses.map((v) => v.toJson()).toList();
}
return data;
}
}
class Responses {
int id;
String comment;
int uid;
int likes;
bool isLikedByUser;
Responses({this.id, this.comment, this.uid, this.likes, this.isLikedByUser});
Responses.fromJson(Map<String, dynamic> json) {
id = json['id'];
comment = json['comment'];
uid = json['uid'];
likes = json['likes'];
isLikedByUser = json['isLikedByUser'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['id'] = this.id;
data['comment'] = this.comment;
data['uid'] = this.uid;
data['likes'] = this.likes;
data['isLikedByUser'] = this.isLikedByUser;
return data;
}
}
Any help is appreciated!
Just for the fun of it - I tried to implement the same thing using json_serializable since I recommended it in my comment. Hopefully this shows you that it is not that complicated - in fact, it is simpler than actually figuring out how to code it your self.
First I started with the blank Flutter project.
Second, I added required dependencies to pubspec.yaml:
dependencies:
flutter:
sdk: flutter
cupertino_icons: ^1.0.2
# Added this
json_annotation: ^4.0.1
dev_dependencies:
flutter_test:
sdk: flutter
# and these two...
build_runner: ^2.0.4
json_serializable: ^4.1.3
Next thing, I created a separate file json_demo.dart, and took part of your code. I also added few things:
part instruction that will include generated json mapping file
For each class added .fromJson named constructor
For each class added toJson() method.
Added #JsonSerializable() for each class - this is how the tool knows which class to look at
Added #JsonKey(name: 'poster_profile_pic') and #JsonKey(name: 'poster_username') - since your filed names are different than Json property names (poster_profile_pic vs posterProfilePic), you need to tell the tool how to rename it back and forth.
Made all properties nullable (since I'm using latest version with null-safety)
import 'package:json_annotation/json_annotation.dart';
part 'json_demo.g.dart';
#JsonSerializable()
class VideoComments {
int? id;
String? comment;
int? uid;
int? likes;
bool? isLikedByUser;
#JsonKey(name: 'poster_profile_pic')
String? posterProfilePic;
#JsonKey(name: 'poster_username')
String? posterUsername;
List<Responses>? responses;
VideoComments(
{this.id,
this.comment,
this.uid,
this.likes,
this.isLikedByUser,
this.posterProfilePic,
this.posterUsername,
this.responses});
factory VideoComments.fromJson(Map<String, dynamic> json) => _$VideoCommentsFromJson(json);
Map<String, dynamic> toJson() => _$VideoCommentsToJson(this);
}
#JsonSerializable()
class Responses {
int? id;
String? comment;
int? uid;
int? likes;
bool? isLikedByUser;
Responses({this.id, this.comment, this.uid, this.likes, this.isLikedByUser});
factory Responses.fromJson(Map<String, dynamic> json) => _$ResponsesFromJson(json);
Map<String, dynamic> toJson() => _$ResponsesToJson(this);
}
Now, simply run flutter pub run build_runner build, and you get json_demo.g.dart file generated:
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'json_demo.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
VideoComments _$VideoCommentsFromJson(Map<String, dynamic> json) {
return VideoComments(
id: json['id'] as int?,
comment: json['comment'] as String?,
uid: json['uid'] as int?,
likes: json['likes'] as int?,
isLikedByUser: json['isLikedByUser'] as bool?,
posterProfilePic: json['poster_profile_pic'] as String?,
posterUsername: json['poster_username'] as String?,
responses: (json['responses'] as List<dynamic>?)
?.map((e) => Responses.fromJson(e as Map<String, dynamic>))
.toList(),
);
}
Map<String, dynamic> _$VideoCommentsToJson(VideoComments instance) =>
<String, dynamic>{
'id': instance.id,
'comment': instance.comment,
'uid': instance.uid,
'likes': instance.likes,
'isLikedByUser': instance.isLikedByUser,
'poster_profile_pic': instance.posterProfilePic,
'poster_username': instance.posterUsername,
'responses': instance.responses,
};
Responses _$ResponsesFromJson(Map<String, dynamic> json) {
return Responses(
id: json['id'] as int?,
comment: json['comment'] as String?,
uid: json['uid'] as int?,
likes: json['likes'] as int?,
isLikedByUser: json['isLikedByUser'] as bool?,
);
}
Map<String, dynamic> _$ResponsesToJson(Responses instance) => <String, dynamic>{
'id': instance.id,
'comment': instance.comment,
'uid': instance.uid,
'likes': instance.likes,
'isLikedByUser': instance.isLikedByUser,
};
Note how it correctly renamed the json property based on the annotation:
posterProfilePic: json['poster_profile_pic'] as String?,
One more thing to notice - this is how it fixed the problem you had:
responses: (json['responses'] as List<dynamic>?)
?.map((e) => Responses.fromJson(e as Map<String, dynamic>))
.toList(),
From now on, each time you change your class, simple re-run the build script.
As you explore further, you'll see that it can handle enums, it has nice annotations to automatically rename all fields in a class from snake case to kebab case (or whatever it is called). But most importantly - does it in a consistent and tested way. As you add more classes, it will really help you save some time...
And to make your life easier, create user snippet in VS Code (File->Preferences->User snippets):
{
"Json Serializible": {
"prefix": "serial",
"body": [
"factory ${1}.fromJson(Map<String, dynamic> json) => _$${1}FromJson(json);",
"Map<String, dynamic> toJson() => _$${1}ToJson(this);"
]
}
}
Here's how to use it:
Copy the name of your class
start typing 'serial' - this is the shortcut for the code snippet
Select the snippet and paste the class name - it will paste it 3 times where needed.
See - simpler than learning how to manually encode/decode Json....
As #Andrija suggested, that is certainly a good way, if you don't want to use that then go ahead with the vscode extension bendixma.dart-data-class-generator, create your class and keep your variables, just do ctrl + shift + p -> Search data class, hit enter when you find dart data class generator from class properties.
Thank you everyone for your responses. I have no resolved the issue.
I have changed my code (in respect to the issue area) to the following:
if (json['responses'].length > 0) {
json['responses'].forEach((e) => responses.add(Responses.fromJson(e)));
} else if (json['responses'].length == 0 || json['responses'] == null) {
responses = null;
}
and on my web server, I have wrapped the "responses" in another (parent) array.
it is an error related to data type. Please cross the the JSON response and Dart class variable data type. String variable can't be an Int or Double value. Or do one thing change all variable into Dynamic type.
But yes it is not good practice to have dynamic as datatype for all variable.

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

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