I want to fetch and format json data from this as a trial in flutter. However, during the formatting process, an exception occurs: type 'Null' is not a subtype of type 'String'.
And these are my code:
user_model.dart
class User {
int id;
String email;
String firstName;
String lastName;
String avator;
User({
required this.id,
required this.email,
required this.firstName,
required this.lastName,
required this.avator
});
factory User.fromJson(Map<String, dynamic> json) => User(
id : json['id'],
email : json['email'],
firstName : json['first_name'],
lastName : json['last_name'],
avator : json['avator']
);
}
user_api.dart
...
class UserApi {
Future<List<User>?> getUsers() async {
final url = Uri.parse('https://reqres.in/api/users?page=2');
try {
final res = await http.get(url);
if (res.statusCode == 200) {
final Map<String, dynamic> body = jsonDecode(res.body);
final List<User> users = body['data'].map((dynamic userData) => {
print('userData : $userData');
User.fromJson(userData) // There seems to be an error here.
}).toList();
return users;
} else {
return null;
}
} catch (e) {
print(e.toString());
}
return null;
}
}
And userData seems like this in my console:
flutter: userData : {id: 7, email: michael.lawson#reqres.in, first_name: Michael, last_name: Lawson, avatar: https://reqres.in/img/faces/7-image.jpg}
I don't think userData is kind of Null, but why do I get the exception?
You need to use json['avatar'] instead of json['avator']
factory User.fromJson(Map<String, dynamic> json) => User(
id : json['id'],
email : json['email'],
firstName : json['first_name'],
lastName : json['last_name'],
avator : json['avatar'] //here `a` instead of `o`
);
I just checked the link you have mentioned for the json you are using. There is a typo at your end. In the json, avatar is the correct field spelling. You have mentioned avator in your class's factory constructor.
So, avator is Null and thus, String avator is assigned to a Null value.
FYI: The error type 'Null' is not a subtype of type 'String' means that you are trying to assign a Null value to a String type variable.
its a typo in the fromJson method : as mentioned by yeasin-sheikh (You need to use json['avatar'] instead of json['avator']),
Yeasin-sheikh's answer
there are some json parsing websites, using that we can easily generate model class and other methods related to it.
eg : app.quicktype.io
just input the json response and generate the model class in required language.
I tried to fetch document data in firestore subcollection then show this error "Null check operator used on a null value " .
I want to fetch one article in user collection for each users.
database screenshot
user table
article subcollection
all articles UI
how to fetch a article when click view button
View button code in All articles UI
ElevatedButton(child: Text('View'),onPressed: () {
Navigator.of(context).push(MaterialPageRoute(builder: (context) => ViewOneUserArticleScreen(id: data[index].id,)));
view one article code
Articles? oneArticle;
bool loading = false;
#override
initState() {
super.initState();
loading = true;
getArticle();
}
User? user = FirebaseAuth.instance.currentUser;
UserModel loggedInUser = UserModel();
Future<void> getArticle() async {
final id = widget.id;
final reference = FirebaseFirestore.instance.doc('users/${user?.uid}/articles/$id');
final snapshot = reference.get();
final result = await snapshot.then(
(snap) => snap.data() == null ? null : Articles.fromJson(snap.data()!));
setState(() {
oneArticle = result;
loading = false;
});
}
model
class Articles {
final String id;
final String topic;
final String description;
final String url;
Articles({
required this.id,
required this.topic,
required this.description,
required this.url
});
Articles.fromJson(Map<String, dynamic> json)
: this(
id: json['id'],
topic: json['topic']! as String,
url: json['url']! as String,
description: json['description']! as String,
);
Map<String, Object?> toJson() {
return {
'id': id,
'topic': topic,
'url': url,
'description': description,
};
}
}
new error
Your Issue is in your parsing method, change your Articles.fromJson to this:
Articles.fromJson(Map<String, dynamic> json)
: this(
id: json['id'] ?? '', // <--- change this
topic: json['topic'] as String ?? '', // <--- change this
url: json['url'] as String ?? '', // <--- change this
description: json['description'] as String ?? '', // <--- change this
);
in your json, topic, description and url may be null but you used ! on them and that means you are sure that they aren't null but they are. Also your id may be null to but in your object model you set it as required, so you need to provide default value to it or just remove the required before it.
error
I tried to fetch user's data from firebase using logged user uid . And also I used model
model code
Details detailsFromJson(String str) => Details.fromJson(json.decode(str));
class Details {
Details({
required this.id,
required this.age,
required this.drinkstalkSE,
required this.drinksUnderstandSE,
required this.familyChildren,
});
String id;
String age;
String drinkstalkSE;
String drinksUnderstandSE;
String familyChildren;
factory Details.fromJson(Map<String, dynamic> json) => Details(
id: json["id"] ?? "",
age: json["age"] ?? "",
drinkstalkSE: json["drinkstalkSE"] ?? "",
drinksUnderstandSE: json["drinksUnderstandSE"] ?? "",
familyChildren: json["familyChildren"] ?? "",
);
Map<String, dynamic> toJson() => {
"id": id,
"age": age,
"drinkstalkSE": drinkstalkSE,
"drinksUnderstandSE": drinksUnderstandSE,
"familyChildren": familyChildren,
};
}
backend code
bool loading = false;
#override
initState() {
super.initState();
loading = true;
getDetails();
}
Details? oneUserDetails;
Future<void> getDetails() async {
final sp = context.read<SignInProvider>();
final id = sp.uid;
final reference = FirebaseFirestore.instance.doc('users/$id');
final snapshot = reference.get();
final result = await snapshot.then(
(snap) => snap.data() == null ? null : Details.fromJson(snap.data()!));
print('result is ====> $result');
setState(() {
oneUserDetails = result;
loading = false;
});
}
screen code
Database image
In my code no any errors show I think problem have in my model but I couldn't understand what is the error and how to solve it. How to solve this error?
The values you use are listed, you need to create a separate section in the class for them. If you don't know exactly how, paste your json data on this site and it will handle it for you. You will see your mistake.
https://javiercbk.github.io/json_to_dart/
According to my knowledge, there is a problem with the model. In the model, the list is drinksUnderstandSE and drinkstalkSE both are strings but in the database, it is the list so it should be a list.
I'm developing a web app using Flutter Web and RESTful API for backend.
So, I'm trying the fetch the data from the api, serialize it by using Flutter Models, then return the result.
The Problem is, I'm getting this result
Expected a value of type 'Map<String, dynamic>', but got one of type 'List<dynamic>'
How to fix this ?
Here's my flutter codes:
models
// To parse this JSON data, do
//
// final medicalRecordsModel = medicalRecordsModelFromJson(jsonString);
import 'dart:convert';
class MedicalRecordsModel {
MedicalRecordsModel({
this.id,
this.category,
this.fileName,
this.dateTimestamp,
this.description,
this.upload,
this.patientName,
this.age,
this.address,
this.userId,
this.patientId,
this.isActive,
});
final String id;
final String category;
final String fileName;
final String dateTimestamp;
final String description;
final String upload;
final String patientName;
final String age;
final String address;
final dynamic userId;
final int patientId;
final bool isActive;
factory MedicalRecordsModel.fromJson(Map<String, dynamic> json) {
return MedicalRecordsModel(
id: json["id"],
category: json["category"],
fileName: json["fileName"],
dateTimestamp: json["dateTimestamp"],
description: json["description"],
upload: json["upload"],
patientName: json["patientName"],
age: json["age"],
address: json["address"],
userId: json["userId"],
patientId: json["patientId"],
isActive: json["isActive"],
);
}
}
API Connection
import 'dart:convert';
import 'dart:developer';
import 'dart:async';
import 'package:app/src/constants/medical_records.dart';
import 'package:app/src/models/medical_records/medical_records.dart';
import 'package:app/src/pages/Medical-Records/medical_record.dart';
import 'package:http/http.dart' as http;
class MedicalRecordsManager {
var client = http.Client();
var url = ConstantMedicalRecords.medical_records_api;
Future<MedicalRecordsModel> getRecords() async {
var url = ConstantMedicalRecords.medical_records_api;
log('$url');
try {
final response = await client.get(url);
if (response.statusCode == 200) {
return MedicalRecordsModel.fromJson(jsonDecode(response.body));
// print(recordsModel);
}
} catch (Exception) {
print(Exception);
print("Error occured");
}
}
}
Here is the JSON data I want to get
{
"id": "103",
"category": "DOCUMENT",
"fileName": "Check Up",
"dateTimestamp": "2021-02-1012:59:46",
"description": "string",
"upload": "String",
"patientName": "1",
"age": "25",
"address": "Earth",
"userId": null,
"patientId": 12,
"isActive": true
}
Please help me with this one.
you can do it like that
MedicalRecordsModel.fromJson(jsonDecode(response.body) as Map<String, dynamic>);
change the getRecord as follows
Future<MedicalRecordsModel> getRecords() async {
var url = ConstantMedicalRecords.medical_records_api;
log('$url');
try {
final response = await client.get(url);
if (response.statusCode == 200) {
return MedicalRecordsModel.fromJson(jsonDecode(response.body)[0]);
// print(recordsModel);
}
} catch (Exception) {
print(Exception);
print("Error occured");
}
}
I think jsonDecode gives list of Maps therefore your json map is the first element of that list.
This code wiil work as you expected:
import 'package:json_helpers/json_helpers.dart';
void main() {
// responseBody is the same response.body
// When response is a list of objects
final list = responseBody1.jsonList((e) => MedicalRecordsModel.fromJson(e));
var obj = list[0];
print(obj.category);
print(obj.fileName);
// When response is an object
obj = responseBody2.json((e) => MedicalRecordsModel.fromJson(e));
print(obj.category);
print(obj.fileName);
}
final responseBody1 = '''
[
{
"id":"103",
"category":"DOCUMENT",
"fileName":"Check Up",
"dateTimestamp":"2021-02-1012:59:46",
"description":"string",
"upload":"String",
"patientName":"1",
"age":"25",
"address":"Earth",
"userId":null,
"patientId":12,
"isActive":true
}
]''';
final responseBody2 = '''
{
"id":"103",
"category":"DOCUMENT",
"fileName":"Check Up",
"dateTimestamp":"2021-02-1012:59:46",
"description":"string",
"upload":"String",
"patientName":"1",
"age":"25",
"address":"Earth",
"userId":null,
"patientId":12,
"isActive":true
}''';
class MedicalRecordsModel {
final String id;
final String category;
final String fileName;
final String dateTimestamp;
final String description;
final String upload;
final String patientName;
final String age;
final String address;
final dynamic userId;
final int patientId;
final bool isActive;
MedicalRecordsModel({
this.id,
this.category,
this.fileName,
this.dateTimestamp,
this.description,
this.upload,
this.patientName,
this.age,
this.address,
this.userId,
this.patientId,
this.isActive,
});
factory MedicalRecordsModel.fromJson(Map<String, dynamic> json) {
return MedicalRecordsModel(
id: json['id'] as String,
category: json['category'] as String,
fileName: json['fileName'] as String,
dateTimestamp: json['dateTimestamp'] as String,
description: json['description'] as String,
upload: json['upload'] as String,
patientName: json['patientName'] as String,
age: json['age'] as String,
address: json['address'] as String,
userId: json['userId'] as String,
patientId: json['patientId'] as int,
isActive: json['isActive'] as bool,
);
}
}
Output:
DOCUMENT
Check Up
DOCUMENT
Check Up
That is, when response is a list of objects:
final list = response.body.jsonList((e) => MedicalRecordsModel.fromJson(e));
When response is an object:
final object = response.body.json((e) => MedicalRecordsModel.fromJson(e));
If you don't know what the result is, then you can try both methods.
response.body.json((e) => Model.fromJson(e));
response.body.jsonList((e) => Model.fromJson(e));
If you have already decoded a JSON string and want to convert the result (or part of it), you can use the following methods:
If the type of the decoded value is Map:
final object = value.json((e) => Model.fromJson(e));
If the type of the decoded value is List:
final objects = value.json((e) => Model.fromJson(e));
Every response is sended and received as text, which can be converted to the
Map Format with the dart inbuilt core library import 'dart:convert';.
So the response from the request can be treated like this.
final res = await http.post(Uri.parse(url), body: json.encode({
'userId': uid,
'email': email,
}),
head body: json.encode({
'userId': uid,
'email': email,
}),
headers: {'Content-Type': 'application/json', 'token64': token});
here json.encode() is used to convert to String from Map.
now res variable contain the response which is also a string which can be convert to the Map with json.decode() like this.
final data = json.decode(res);
when working with the data sometimes we occur errors like Map is not a type of Map<String, String> etc.
Which can be solved by type casting the res, like this.
Map<String, String> notification = Map<String, String>.from(data['notification']);
I see these type casting method used in the The boring Flutter Development show in Youtube.
I faced the same kind of problem after I built an API and tried consuming it in flutter. I first extracted the data and check if the extracted data is null. When the condition is false, I made a list loadStudents that will hold the data after the loop. This is what worked out for me after a ton of stress looking for solutions online.
i have a Firestore like the following :
My goal is to map each entry from the collection of days -> 'uid' -> collection to a datamodel called "Day" and return it as a stream to Provider.
Every entry in this collection in a date, which is holding a reference to a transfer.
This is the transfer storage :
This is the Day Datamodel :
class Day {
Day({this.date, this.transfers});
final String date;
final List<Transfer> transfers;
}
This is the code i tried (which is currently missing the deserializing of the List of Transfers, but i was lost at this point) :
Stream<List<Day>> get dayTransferData {
return daysCollection.document('QeG5SgSoYPXCpPkU86Z9ReShr2j2').collection('').snapshots().map(_brewListFromSnapshot);
}
List<Day> _brewListFromSnapshot(QuerySnapshot snapshot) {
return snapshot.documents.map((doc) {
return Day(
date: doc.documentID,
transfers: doc.data.values,
);
}).toList();
}
I searched on stackoverflow but everyone was referencing the collection by name.
How do i get the data of the collection and map it in the correct way ?
User class with JSON convert: JSON and serialization
class User {
String name;
int age;
User({
this.name,
this.age,
});
factory User.fromJson(String str) => User.fromMap(json.decode(str));
String toJson() => json.encode(toMap());
factory User.fromMap(Map<String, dynamic> json) => User(
name: json["name"],
age: json["age"],
);
Map<String, dynamic> toMap() => {
"name": name,
"age": age,
};
}
Create user list :
users = jsonList.map((json) => User.fromJson(json)).toList();