Hello in my flutter project i got this problem when i want to recall users by thier ID.
Future<UserModel> getUserById(String id)=> _firestore.collection(collection).doc(id){
print("==========id is $id=============");
debugPrint("==========NAME is ${doc.data()['name']}=============");
debugPrint("==========NAME is ${doc.data()['name']}=============");
it gives an error on [ .doc(id){ ]
what shall i do?
an also in my order page it gives same error somehow
_firestore.collection(collection).doc(id).setData()({
"userId": userId,
"cart": convertedCart,
"id": id,
"total": totalPrice,
"createdAt": DateTime.now().millisecondsSinceEpoch,
"description": description,
"status": status
});
}
what do you guys think?
in that line
_firestore.collection(collection).doc(id).setData()({
setData is error
my flutter version is 2.5.1
Try the code below.
Future<UserModel> getUserById(String id){
return FirebaseFirestore.instance.collection("collectionPath")
.doc(id).get().then((doc) => UserModel.fromSnapShot(doc.data()));
}
Your fromSnapshot don't return a UserModel. It should look like this.
import 'package:flutter/foundation.dart';
#immutable
class UserModel{
final String id;
final String name;
final String email;
final String stripeId;
final List<CartItemModel> cart;
final int totalCartPrice;
const UserModel({required this.id, required this.name, required this.email, required this.stripeId, required this.cart,
required this.totalCartPrice});
Map<String, dynamic> toMap() {
return {
'id': id,
'name': name,
'email': email,
'stripeId': stripeId,
'cart': cart,
'totalCartPrice': totalCartPrice,
};
}
factory UserModel.fromMap(Map<String, dynamic> map) {
return UserModel(
id: map['id'] as String,
name: map['name'] as String,
email: map['email'] as String,
stripeId: map['stripeId'] as String,
cart: (map['cart'] as List).map((cart) => CartItemModel.fromMap(cart)).toList() ,
totalCartPrice: map['totalCartPrice'] as int,
);
}
}
#immutable
class CartItemModel{
final String id;
const CartItemModel({required this.id});
Map<String, dynamic> toMap() {
return {
'id': id,
};
}
factory CartItemModel.fromMap(Map<String, dynamic> map) {
return CartItemModel(
id: map['id'] as String,
);
}
}
Related
I'm trying to Integrate the API using model. Let say I have a book screen, so I'm trying to get its API data using model. my model looks like this.
class Book {
final int id;
final String phone;
final String name;
final String relation;
final String updated_at;
final String created_at;
final int userId;
Book(
{required this.id,
required this.name,
required this.phone,
required this.relation,
required this.created_at,
// required this.image,
required this.updated_at,
required this.userId,
});
factory Book.fromJson(Map<String, dynamic> json) => Book(
id: json['user_id'],
name: json['contact_person'],
relation: json['relation'],
phone: json['phone'],
updated_at: json['updated_at'],
created_at: json['created_at'],
userId: json['id']
);
Map<String, dynamic> toJson() => {
'user_id': userId,
'contact_person': phone,
'relation': relation,
'name': name,
'created_at':created_at,
'updated_at':updated_at,
'id':id,
};
}
calling this api like this
Future<List<Book>> getBook() async {
List<Book> _bookList =[];
Map<String, String> headers = {
"Content-type": "application/json",
'Authorization': 'Bearer $token',
};
var url = Uri.parse(ApiPath.getAllEmergenceyContactUrl);
final response = await http.get(url, headers: headers);
if (response.statusCode == 200) {
Map<String, dynamic> map = json.decode(response.body);
List<dynamic> data = map["user"];
if(data.length>0){
for(int i=0;i<data.length;i++){
if(data[i]!=null){
Map<String,dynamic> map=data[i];
_bookList.add(Book.fromJson(map));
debugPrint('Id-------${map['contact_person']}'); //this print the correct data
}
}
}
print(_bookList);
return _bookList;
} else {
// If that call was not successful, throw an error.
throw Exception('Failed to load post');
}
}
print(_bookList); this give me this output
[Instance of 'Book', Instance of 'Book']
and calling in User Interface like this
List<Book> books = [];
getAllEmergenceyContacts()async{
var books = await services.getBook();
}
i can't able to get the the when using the books in listview builder, please help me out.
my json data look like this
{
"status": 1,
"message": "your emergency contacts",
"user": [
{
"id": 10,
"user_id": 49,
"contact_person": "ABC",
"relation": "DSVKJDSB",
"phone": "sdfsdf",
"image": "emergency/1735686398652391.png",
"created_at": "2022-06-15T07:52:19.000000Z",
"updated_at": "2022-06-15T07:52:19.000000Z"
},
]}
and i want user array data from it.
I optimized your code and fix your problem. You can try it and tell me if have any problem
Model
import 'dart:convert';
Book bookFromJson(String str) => Book.fromJson(json.decode(str));
String bookToJson(Book data) => json.encode(data.toJson());
class Book {
Book({
this.status,
this.message,
this.user,
});
int status;
String message;
List<User> user;
factory Book.fromJson(Map<String, dynamic> json) => Book(
status: json["status"],
message: json["message"],
user: List<User>.from(json["user"].map((x) => User.fromJson(x))),
);
Map<String, dynamic> toJson() => {
"status": status,
"message": message,
"user": List<dynamic>.from(user.map((x) => x.toJson())),
};
}
class User {
User({
this.id,
this.userId,
this.contactPerson,
this.relation,
this.phone,
this.image,
this.createdAt,
this.updatedAt,
});
int id;
int userId;
String contactPerson;
String relation;
String phone;
String image;
DateTime createdAt;
DateTime updatedAt;
factory User.fromJson(Map<String, dynamic> json) => User(
id: json["id"],
userId: json["user_id"],
contactPerson: json["contact_person"],
relation: json["relation"],
phone: json["phone"],
image: json["image"],
createdAt: DateTime.parse(json["created_at"]),
updatedAt: DateTime.parse(json["updated_at"]),
);
Map<String, dynamic> toJson() => {
"id": id,
"user_id": userId,
"contact_person": contactPerson,
"relation": relation,
"phone": phone,
"image": image,
"created_at": createdAt.toIso8601String(),
"updated_at": updatedAt.toIso8601String(),
};
}
Call API
Future getBook() async {
Map<String, String> headers = {
"Content-type": "application/json",
'Authorization': 'Bearer $token',
};
var url = Uri.parse(ApiPath.getAllEmergenceyContactUrl);
final response = await http.get(url, headers: headers);
if (response.statusCode == 200) {
return bookFromJson(response.body).user;
} else {
// If that call was not successful, throw an error.
throw Exception('Failed to load post');
}
}
Calling in ui screen
List<Book> books = [];
getAllEmergenceyContacts()async{
books = await services.getBook();
setState((){});
}
Listview builder
ListView.builder(
itemCount: books.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(books[index].name),
);
},
),
print(_bookList); this gives you this output [Instance of 'Book', Instance of 'Book'] because you try to print every Book class instance
You declare List<Book> _bookList =[]; , where _bookList holds Book Class as a child.
At first, Fetch the books from API
List<Book> books = [];
getAllEmergenceyContacts()async{
var books = await services.getBook();
}
Then, you Should place all the books inside List view builder like the following way
ListView.builder(
itemCount: books.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(books[index].name),
);
},
),
I am getting data from an API using a model. But I ran into a problem that when I get the 'gallery' data, I get an error, that is, I get the data incorrectly. I need to get the 'gallery' field and inside it take the 'url' field - a link to the photo, in order to use it in the future. Can you tell me how to get the 'url' field correctly?
{
"data": {
"id": 35,
"picture_url": null,
"email_confirmed": false,
"gallery": [
{
"url": "https://picture-staging.s3.eu-central.jpeg",
"mime_type": "image/jpeg",
"type": "gallery",
"updated_at": "2022",
"created_at": "2022"
}
],
"updated_at": "2022",
"created_at": "2022"
}
}
model
class User {
final int id;
List? gallery;
User({
required this.id,
this.gallery,
});
User.fromJson(Map<String, dynamic> json)
: this(
id: json['id'] as int,
gallery: json['gallery']['url'],
);
In your API response, there is a list of gallery objects therefore you have to traverse through all of them.
User.fromJson(Map<String, dynamic> json) {
json = json['data'];
id = json['id'];
pictureUrl = json['picture_url'];
emailConfirmed = json['email_confirmed'];
if (json['gallery'] != null) {
gallery = <Gallery>[];
json['gallery'].forEach((v) {
gallery!.add(new Gallery.fromJson(v));
});
}
updatedAt = json['updated_at'];
createdAt = json['created_at'];
}
There are multiple tools that helps you create that .fromJson method, like this. Paste your json there and it will generate dart code for you, really helps me.
The usage should like this:
User user = User.fromJson(yourApiResponseJson);
print(user.id);
print(user.gallery); //prints entire list of gallery
print(user.gallery.first.url); //prints only first object url
I hope that is not your whole model, because that model is not accessing the "data" key on the json response, your model should start getting the key data then pass it to another class that in this case should be named User
here is a brief example
class User {
User({
required this.data,
});
final Data data;
factory User.fromJson(Map<String, dynamic> json) => User(
data: Data.fromJson(json["data"]),
);
}
The Data class could be like this:
class Data {
Data({
required this.id,
required this.pictureUrl,
required this.emailConfirmed,
required this.gallery,
required this.updatedAt,
required this.createdAt,
});
final int id;
final dynamic pictureUrl;
final bool emailConfirmed;
final List<Gallery> gallery;
final String updatedAt;
final String createdAt;
factory Data.fromJson(Map<String, dynamic> json) => Data(
id: json["id"],
pictureUrl: json["picture_url"],
emailConfirmed: json["email_confirmed"],
gallery: List<Gallery>.from(json["gallery"].map((x) => Gallery.fromJson(x))),
updatedAt: json["updated_at"],
createdAt: json["created_at"],
);
}
I reccomend you using Quicktype
Hey you can use this tool to generate your dart model from json.
Below is generated code from above tool
// final user = userFromJson(jsonString);
import 'dart:convert';
User userFromJson(String str) => User.fromJson(json.decode(str));
String userToJson(User data) => json.encode(data.toJson());
class User {
User({
required this.data,
});
Data data;
factory User.fromJson(Map<String, dynamic> json) => User(
data: Data.fromJson(json["data"]),
);
Map<String, dynamic> toJson() => {
"data": data.toJson(),
};
}
class Data {
Data({
this.id,
this.pictureUrl,
this.emailConfirmed,
this.gallery,
this.updatedAt,
this.createdAt,
});
int? id;
String? pictureUrl;
bool? emailConfirmed;
List<Gallery>? gallery;
String? updatedAt;
String? createdAt;
factory Data.fromJson(Map<String, dynamic> json) => Data(
id: json["id"],
pictureUrl: json["picture_url"],
emailConfirmed: json["email_confirmed"],
gallery: List<Gallery>.from(json["gallery"].map((x) => Gallery.fromJson(x))),
updatedAt: json["updated_at"],
createdAt: json["created_at"],
);
Map<String, dynamic> toJson() => {
"id": id,
"picture_url": pictureUrl,
"email_confirmed": emailConfirmed,
"gallery": List<dynamic>.from(gallery.map((x) => x.toJson())),
"updated_at": updatedAt,
"created_at": createdAt,
};
}
class Gallery {
Gallery({
this.url,
this.mimeType,
this.type,
this.updatedAt,
this.createdAt,
});
String? url;
String? mimeType;
String? type;
String? updatedAt;
String? createdAt;
factory Gallery.fromJson(Map<String, dynamic> json) => Gallery(
url: json["url"],
mimeType: json["mime_type"],
type: json["type"],
updatedAt: json["updated_at"],
createdAt: json["created_at"],
);
Map<String, dynamic> toJson() => {
"url": url,
"mime_type": mimeType,
"type": type,
"updated_at": updatedAt,
"created_at": createdAt,
};
}
// You can use like this
final user = userFromJson(jsonString);
String? url = user.data?.gallery?.url;
I am fetching one row from a database and sending it to flutter where I decode it to receive the following response using var userProfile = json.decode(response.body);
[{id: 1, first_name: First, last_name: Last, name: david, email: david4001#gmail.com, phone_number: 12, user_image: null, email_verification_code: null, email_verification_time: null, created_at: 2022-03-24T17:37:17.000000Z, updated_at: 2022-03-29T07:16:25.000000Z}]
I have a UserProfile class
class UserProfile {
final int id;
final String firstName;
final String lastName;
final String email;
final String phoneNumber;
UserProfile({
required this.id,
required this.firstName,
required this.lastName,
required this.email,
required this.phoneNumber,
});
factory UserProfile.fromJson(Map<String, dynamic> json) {
return UserProfile(
id: json["id"],
firstName: json["first_name"],
lastName: json["first_name"],
email: json["email"],
phoneNumber: json["phone_number"],
);
}
}
I am using the following code to find a suitable way to display the data
UserProfile? userProfile;
if (response.statusCode == 200) {
var userProfile = json.decode(response.body);
List<UserProfile> myProfile = [];
for (var k in userProfile) {
myProfile.add(UserProfile.fromJson(userProfile));
}
} else {
// If the server did not return a 200 OK response,
// then throw an exception.
throw Exception('Failed to load user data');
}
I am getting the error below
Unhandled Exception: type 'List<dynamic>' is not a subtype of type 'Map<String, dynamic>'
How do I handle the error?
You are passing whole list instead of value.
Try this.
var userProfile = json.decode(response.body);
List<UserProfile> myProfile = [];
for (var k in userProfile) {
myProfile.add(UserProfile.fromJson(k));
}
You will try like this way
const myJson = """
[
{
"id": 1,
"first_name": "First",
"last_name": "Last",
"name": "david",
"email": "david4001#gmail.com",
"phone_number": "12",
"user_image": null,
"email_verification_code": null,
"email_verification_time": null,
"created_at": "2022-03-24T17:37:17.000000Z",
"updated_at": "2022-03-29T07:16:25.000000Z"
}
]
""";
class UserProfile {
UserProfile({
this.id,
this.firstName,
this.lastName,
this.name,
this.email,
this.phoneNumber,
this.userImage,
this.emailVerificationCode,
this.emailVerificationTime,
this.createdAt,
this.updatedAt,
});
int? id;
String? firstName;
String? lastName;
String? name;
String? email;
String? phoneNumber;
dynamic userImage;
dynamic emailVerificationCode;
dynamic emailVerificationTime;
DateTime? createdAt;
DateTime? updatedAt;
factory UserProfile.fromMap(Map<String, dynamic> json) => UserProfile(
id: json["id"],
firstName: json["first_name"],
lastName: json["last_name"],
name: json["name"],
email: json["email"],
phoneNumber: json["phone_number"],
userImage: json["user_image"],
emailVerificationCode: json["email_verification_code"],
emailVerificationTime: json["email_verification_time"],
createdAt: DateTime.parse(json["created_at"]),
updatedAt: DateTime.parse(json["updated_at"]),
);
}
void main() {
final userData = List.from(json.decode(myJson));
print(userData[0]['id']);
print(userData[0]['name']);
}
I am trying to connect my flutter app to RESTful API. But I am having some problems. This is just the authentication part.
When I am sending a POST request for Register, I am getting user id as null in the response.
Below is my user model file:
import 'dart:convert';
User userFromJson(String str) => User.fromJson(json.decode(str));
String userToJson(User data) => json.encode(data.toJson());
class User {
final String id;
final String username;
final String profileImageUrl;
final String email;
User({
this.id,
this.username,
this.profileImageUrl,
this.email,
});
factory User.fromJson(Map<String, dynamic> json) => User(
id: json["id"],
username: json["username"],
profileImageUrl: json["image"],
);
Map<String, dynamic> toJson() => {
"id": id,
"username": username,
"image": profileImageUrl,
};
}
And this is the response I should be getting from API:
{
"user": {
"id": 2,
"username": "Davrick"
},
"image": null
}
Here is my register function:
static Future<User> createUser(
String email, String username, String password) async {
final response = await http.post("$apiURL/en/users/register/", body: {
"username": username,
"password": password,
"email": email,
});
if (response.statusCode != null) {
final String responseString = response.body;
return userFromJson(responseString);
} else {
return null;
}
}
And when I want to get user id, it is showing it as null although in the server I can see that it is adding users with new IDs.
_user != null
? Text(
"The user ${_user.username} with id ${_user.id} is created successfully.")
: Text("No users"),
Your fromJson constructor needs to first go through the user submap. Passing a key to the top level map does not search nested ones.
factory User.fromJson(Map<String, dynamic> json) => User(
id: json['user']["id"],
username: json['user']["username"],
profileImageUrl: json["image"],
);
Trying to get the value of a key that does not exist in a Map will return null, which is why you're seeing null, but not getting any exceptions.
You should likely do the same for toJson.
Map<String, dynamic> toJson() => {
"user": {
'id': id,
'username': username,
},
"image": profileImageUrl,
};
It turns out the OP posted an incorrect JSON format. With the correct format, the following will work.
factory User.fromJson(Map<String, dynamic> json){
return User(
id: json["user_id"],
username: json["username"],
profileImageUrl: json["image"],
);
}
I'm trying to create classes to match my firestore schema. My schema in firestore is
docID
------------>↓location //Map
↓country //Map
name: "Ireland"
code: "IRE"
↓suburb //Map
name: "Cork"
code: "crk"
↓postcode //Map
name: "4"
code: "4"
I'm a little confused how to model the above. This is what I've done so far..
class VoterData {
VoterData({this.location});
final Location location;
Map<String, dynamic> toMap() {
return {
'location': location,
};
}
factory VoterData.fromMap(Map<String, dynamic> map) {
return VoterData(location: map['location']);
}
}
class Location {
final Suburb suburb;
final Postcode postcode;
final Country country;
Location({this.suburb, this.country, this.postcode});
factory Location.fromJson(Map<String, dynamic> json) => Location(
suburb: json['suburb'],
postcode: json['postcode'],
country: json['country'],
);
Map<String, dynamic> toJson() => {
"suburb": suburb,
"postcode": postcode,
"country": country,
};
}
class Suburb {
String code;
String name;
Suburb({
this.code,
this.name,
});
factory Suburb.fromJson(Map<String, dynamic> json) => Suburb(
code: json["code"],
name: json["name"],
);
Map<String, dynamic> toJson() => {
"code": code,
"name": name,
};
}
class Postcode {
String code;
String name;
Postcode({
this.code,
this.name,
});
factory Postcode.fromJson(Map<String, dynamic> json) => Postcode(
code: json["code"],
name: json["name"],
);
Map<String, dynamic> toJson() => {
"code": code,
"name": name,
};
}
class Country {
String code;
String name;
Country({
this.code,
this.name,
});
factory Country.fromJson(Map<String, dynamic> json) => Country(
code: json["code"],
name: json["name"],
);
Map<String, dynamic> toJson() => {
"code": code,
"name": name,
};
}
I'll looking for my firestore data to be strongly typed to my object model. Suppose I need to write a suburb object to firestore. How would I design my model class ..?
Hi I recommend you use like this class
class DocumentModel {
String collection;
String documentID;
Map<String, dynamic> data;
DataBaseModel(this.collection);
}
class VoterModel extends DocumentModel {
Map<String, dynamic> data = {
'country': { 'name':'', 'code':''},
'suburb': { 'name':'', 'code':'' },
'postcode' : { 'name':'', 'code':'' }
}
VoterModel() : super('<COLLECTION NAME>');
}
so when you get a QuerySnapshot you can parse like this
List<VoterModel> list = querySnapshot.documents.map((DocumentSnapshot docSnapshot) {
VoterModel voter = new VoterModel();
voter.documentID = docSnapshot.documentID;
voter.data = docSnapshot.data;
return voter;
}).toList();
Access to data
list.last.data['country']['name']