Here is my List of maps. But I want to convert these to string.
[{tid: 20210813, title: hello3, description: hello good evening every one, _id: 62ecc3f047ff077fe8d4549e}, {tid: 20210812, title: hello, description: hello good evening every one, _id: 62ecc3f047ff077fe8d4549d}, {tid: 20210814, title: hello4, description: hello good evening every one, _id: 62ecc3f047ff077fe8d4549f}, {tid: 20210812, title: hello, description: hello good evening every one, _id: 62ecc3f047ff077fe8d454a0}, {tid: 20210812, title: hello, description: hello good evening every one, _id: 62ece09647ff077fe8d454e6}, {tid: 20210812, title: hello, description: hello good evening every one, _id: 62ece09647ff077fe8d454e9}, {tid: 20210813, title: 2766767236, description: hello good evening every one, _id: 62ece09647ff077fe8d454e7}, {tid: 20210814, title: hello4, description: hello good evening every one, _id: 62ece09647ff077fe8d454e8}]
You can use this model class
import 'dart:convert';
class ModelClass {
final int? tid;
final String? title;
final String? description;
final String? sId;
ModelClass({
this.tid,
this.title,
this.description,
this.sId,
});
Map<String, dynamic> toMap() {
final result = <String, dynamic>{};
if (tid != null) {
result.addAll({'tid': tid});
}
if (title != null) {
result.addAll({'title': title});
}
if (description != null) {
result.addAll({'description': description});
}
if (sId != null) {
result.addAll({'sId': sId});
}
return result;
}
factory ModelClass.fromMap(Map<String, dynamic> map) {
return ModelClass(
tid: map['tid']?.toInt(),
title: map['title'],
description: map['description'],
sId: map['sId'],
);
}
String toJson() => json.encode(toMap());
factory ModelClass.fromJson(String source) =>
ModelClass.fromMap(json.decode(source));
}
And to get items
final data = jsonDecode(response.body) as List;
return data.map((e) => ModelClass.fromMap(e)).toList();
You need to decode the response into json before getting values
getAllTodos(BuildContext context) async {
try {
var todos = await _homeRepo.getAllTodos(context);
return todoFromJson(jsonDecode(todos));
}
catch (e) {
Fluttertoast.showToast(msg: e.toString()); return null;
}
}
You didn't phrase your question very clearly, but here's some speculation.
First, the map itself has the wrong structure. This is what the correct one looks like:
List myList = [
{
'tid': 20210813,
'title': 'hello3',
'description': 'hello good evening every one',
'_id': '62ecc3f047ff077fe8d4549e'
},
{}
];
You can convert everything to a string with a simple command toString(). Do a for and call toString().
main() {
String str = myList.toString(); // or all
for (final m in myList ){
m.toString();
}
}
However, I assume that in your case you need to convert the maps into a model class by presenting a toJson()/fromJson() or toString()/fromString() method for conversions.
Related
I'm learning flutter by making an app following some youtube tutorials.
I have problem with showing search results in the app view. I'm able to query and get data from node backend but there's this error while mapping the json to model.
The data I'm getting from api is like this:
{id: <uuid>,
userEmail: <email_string>,
profile: [{profileName: <profile_name_string>,
profileImage: <image_url_string>,
profileBio: <profile_bio_string>}]
}
The error shows up in the profileName mapping line in the model.dart file.
class AccountModel {
String userId;
String userEmail;
String? userPassword;
AccountModel({
required this.userId,
required this.userEmail,
this.userPassword,
});
}
class ProfileModel {
AccountModel accountModel;
String? profileName;
String profileImage;
String? profileBio;
ProfileModel({
required this.accountModel,
this.profileName,
required this.profileImage,
this.profileBio,
});
factory ProfileModel.fromMap({required Map<String, dynamic> map}) {
print(map);
return ProfileModel(
profileName: map['profile']['profileName'],
profileImage: map['profile']['profileImage'] ?? "default",
profileBio: map['profile']['profileBio'],
accountModel: AccountModel(
userId: map['id'],
userEmail: map['userEmail'],
userPassword: map['userPassword'],
),
);
}
factory ProfileModel.fromMapFollowerData(
{required Map<String, dynamic> map}) {
return ProfileModel(
profileName: map['profileName'],
profileImage: map['profileImage'] ?? "default",
profileBio: map['profileBio'],
accountModel: AccountModel(
userId: map['userId'],
userEmail: map['userEmail'],
),
);
}
}
Maybe I don't understand this correctly but I think that because the profile data is in [] I need to specify index.
How to rectify this error?
EDIT: New model after updating as guided by Majid:
class AccountModel {
String userId;
String userEmail;
String? userPassword;
final List<ProfileModel>? profile;
AccountModel({
required this.userId,
required this.userEmail,
this.userPassword,
this.profile,
});
factory AccountModel.fromJson({required Map<String, dynamic> map}) {
return AccountModel(
userId: map['id'],
userEmail: map['userEmail'],
userPassword: map['userPassword'],
profile: map['profile']
.map((profileJson) => ProfileModel.fromJson(profileJson))
.toList(),
);
}
}
class ProfileModel {
String profileName;
String profileImage;
String? profileBio;
ProfileModel({
required this.profileName,
required this.profileImage,
this.profileBio,
});
factory ProfileModel.fromJson(profileJson, {Map<String, dynamic>? map}) {
if (map != null) {
return ProfileModel(
profileName: map['profileName'],
profileImage: map['profileImage'] ?? "default",
profileBio: map['profileBio'],
);
} else {
return ProfileModel(
profileName: profileJson['profileName'],
profileImage: profileJson['profileImage'] ?? "default",
profileBio: profileJson['profileBio'],
);
}
}
}
I was getting some errors because of how some functions in other pages that use the model are set up, so I made a few changes. I don't have errors in account/profile creation, post creation pages but still with the search page I have error. The error with the list now is:type 'List<dynamic>' is not a subtype of type 'List<ProfileModel>?'.
The error is where account model is mapping profile model and adding it to list. I tried making the list typed like:.toList<ProfileModel>(),, which I'm sure was stupid coz it shows NoSuchMethodError (NoSuchMethodError: Class 'MappedListIterable<dynamic, dynamic>' has no instance method 'toList' with matching arguments. Receiver: Instance of 'MappedListIterable<dynamic, dynamic>' Tried calling: toList<ProfileModel>() Found: toList({bool growable}) => List<X0>)
The problem here is that profile is a List or Array of Map<String, String> here is your example
...
profile: [
{profileName: <profile_name_string>,
profileImage: <image_url_string>,
profileBio: <profile_bio_string>}
]
which means when you want to access this you have to iterate over the List to convert them all.
Which means this line in your model would become
profileName: map['profile'][0]['profileName'],
profileImage: map['profile'][0]['profileImage'] ?? "default",
profileBio: map['profile'][0]['profileBio'],
However, this has a potential problem. Because you might have a List with no members which mean map['profile'][0] might be empty or null and another problem is that how about a time that profile has more than one member like you have map['profile][0] and map['profile'][1] and so on? in this case you are missing some of the members.
You can stick to only 0 index if you are sure that you always have a member and only one in your profile List but if you want to do this better you should probably do this like:
class UserAccountModel {
UserAccountModel({
this.id,
this.userEmail,
this.profile,
});
final String? id;
final String? userEmail;
final List<ProfileModel>? profile;
factory UserAccountModel.fromJson(Map<String, dynamic> map) {
final profile = map['profile'] as List<dynamic> ;
return UserAccountModel(
id: map['id'],
userEmail: map['userEmail'],
profile: profile.map((profileJson) => ProfileModel.fromJson(profileJson)).toList(),
);
}
}
class ProfileModel {
ProfileModel({
this.profileName,
this.profileImage,
this.profileBio,
});
final String? profileName;
final String? profileImage;
final String? profileBio;
factory ProfileModel.fromJson(Map<String, String> map) {
return ProfileModel(
profileName: map['profileName'],
profileImage: map['profileImage'] ?? "default",
profileBio: map['profileBio'],
);
}
}
I strongly suggest you use json_serializable to avoid any mistakes.
#I am able to fetch id name address but i am not able to fetch image which is src which is inside image need help
#This is my model class
class CategoryModel with ChangeNotifier{
CategoryModel({
this.id,
this.name,
this.slug,
this.parent,
this.description,
this.display,
this.image,
this.menuOrder,
this.count,
this.yoastHead,
this.yoastHeadJson,
this.links,
});
int? id;
String? name;
String? slug;
int? parent;
String? description;
String? display;
Image? image;
int? menuOrder;
int? count;
String? yoastHead;
YoastHeadJson? yoastHeadJson;
Links? links;
factory CategoryModel.fromJson(Map<String, dynamic> json) => CategoryModel(
id: json["id"],
name: json["name"],
slug: json["slug"],
parent: json["parent"],
description: json["description"],
display: json["display"],
image: json["image"] == null ? null : Image.fromJson(json["image"]),
menuOrder: json["menu_order"],
count: json["count"],
yoastHead: json["yoast_head"],
yoastHeadJson: YoastHeadJson.fromJson(json["yoast_head_json"]),
links: Links.fromJson(json["_links"]),
);
Map<String, dynamic> toJson() => {
"id": id,
"name": name,
"slug": slug,
"parent": parent,
"description": description,
"display": display,
"image": image == null ? null : image!.toJson(),
"menu_order": menuOrder,
"count": count,
"yoast_head": yoastHead,
"yoast_head_json": yoastHeadJson!.toJson(),
"_links": links!.toJson(),
};
}
class Image {
Image({
this.id,
this.dateCreated,
this.dateCreatedGmt,
this.dateModified,
this.dateModifiedGmt,
this.src,
this.name,
this.alt,
});
int? id;
DateTime? dateCreated;
DateTime? dateCreatedGmt;
DateTime? dateModified;
DateTime? dateModifiedGmt;
String? src;
String? name;
String? alt;
factory Image.fromJson(Map<String, dynamic> json) => Image(
id: json["id"],
dateCreated: DateTime.parse(json["date_created"]),
dateCreatedGmt: DateTime.parse(json["date_created_gmt"]),
dateModified: DateTime.parse(json["date_modified"]),
dateModifiedGmt: DateTime.parse(json["date_modified_gmt"]),
src: json["src"],
name: json["name"],
alt: json["alt"],
);
Map<String, dynamic> toJson() => {
"id": id,
"date_created": dateCreated!.toIso8601String(),
"date_created_gmt": dateCreatedGmt!.toIso8601String(),
"date_modified": dateModified!.toIso8601String(),
"date_modified_gmt": dateModifiedGmt!.toIso8601String(),
"src": src,
"name": name,
"alt": alt,
};
}
#This is how i try to fetch data. i am trying to fetch data and store that data in a list so that i can render that data according to my design
Future<void> fetchCategory(BuildContext context) async{
const url = "https://sweet-ardinghelli.3-108-138-206.plesk.page/wp-json/wc/v3/products/categories";
try{
final response = await http.get(Uri.parse(url));
final extractedData = json.decode(response.body);
print(extractedData);
List<CategoryModel> loadedData = [];
if(extractedData == null){
ScaffoldMessenger.of(context).showSnackBar(const SnackBar(
content: Text("Data is Null failed to fetch data!"),
duration: Duration(seconds: 3),));
}
extractedData.forEach((element){
loadedData.add(CategoryModel(
id:element['id'],
name:element['name'],
image: element['image']['src']
// image: element!['image']
// image: element['image']==null?Text("no Image to show"):element['image']['src']
));
});
_cItems = loadedData;
print(_cItems);
notifyListeners();
}catch(e){
rethrow;
}
}
#But i am unable to fetch image Image is in nested data like this
[
{id: 25,
name: Bakery,
slug: bakery,
parent: 0,
description: ,
display: products,
image: {
id: 83,
date_created: 2021-07-16T12:16:24,
date_created_gmt: 2021-07-16T12:16:24,
date_modified: 2021-07-16T12:16:24,
date_modified_gmt: 2021-07-16T12:16:24,
src: https://sweet-ardinghelli.3-108-138-206.plesk.page/wp-content/uploads/2021/07/Intersection.png,
name: Intersection,
alt:
}
]
#I wanna fetch the src inside Image
Shouldn't you use the fromJson method that you have declared in the CategoryModel?
*edit
Something like this:
loadedData.add(CategoryModel.fromJson(element));
**edit
How to filter data?
Future<void> fetchCategory(BuildContext context) async{
const url = "https://sweet-ardinghelli.3-108-138-206.plesk.page/wp-json/wc/v3/products/categories";
try{
final response = await http.get(Uri.parse(url));
final extractedData = json.decode(response.body);
print(extractedData);
List<CategoryModel> loadedData = [];
if(extractedData == null){
ScaffoldMessenger.of(context).showSnackBar(const SnackBar(
content: Text("Data is Null failed to fetch data!"),
duration: Duration(seconds: 3),));
}
extractedData.forEach((element){
// Something like this to filter the elements before adding to list.
final item = CategoryModel.fromJson(element);
if(item.on_sale == true){
loadedData.add(CategoryModel.fromJson(element));
}
});
_cItems = loadedData;
print(_cItems);
notifyListeners();
}catch(e){
rethrow;
}
}
Use https://app.quicktype.io/ to easily create model classes to parse from and to json.
And yes, it is available to dart and so many other languages.
At the moment, I am building a Flutter app to try and develop my skills, which includes a search delegate function. At the moment, my search delegate works great, when the data is imported from json format, which looks like this:
[
{
name: John,
age: 22,
height: 1.85,
searchTerm: John 22 1.85,
},
{
name: Alice,
age: 24,
height: 1.90,
searchTerm: Alice 24 1.90,
},
{
name: Bruce,
age: 35,
height: 1.76,
searchTerm: Bruce 35 1.76,
}
]
To allow my search delegate to work, I built a getter model that looks like this.
import 'dart:convert';
import 'package:flutter/services.dart';
class People {
final String name;
final double age;
final double height;
final String searchTerm;
People({
required this.name,
required this.age,
required this.height,
required this.searchTerm,
});
static People fromJson(Map<String, dynamic> json) => People(
name: json['name'],
age: json['age'],
height: json['height'],
searchTerm: json['searchTerm'],
);
}
class PeopleGetter {
static Future<List<People>> getPeopleSuggestions(String query) async {
try {
final String response =
await rootBundle.loadString('assets/data/people.json');
final List people = json.decode(response);
return people
.map((json) => People.fromJson(json))
.where((people) {
final searchTermLower = people.searchTerm.toLowerCase();
final queryLower = query.toLowerCase();
return searchTermLower.contains(queryLower);
}).toList();
} catch (e) {
print(e);
}
throw '';
}
}
This actually does work perfectly with my search delegate. However, since storing the data in a CSV file can significantly reduce the overall data size, and therefore the overall app size, I want to replace the json data with CSV data. I've tried modifying my 'getter' function from json data, to use CSV data (using the CSV package, from pub.dev), which you can see here:
import 'package:csv/csv.dart';
import 'package:flutter/services.dart';
class People {
final String name;
final double age;
final double height;
final String searchTerm;
People({
required this.name,
required this.age,
required this.height,
required this.searchTerm,
});
static People fromCSV(Map<String, dynamic> csv) => People(
name: csv['name'],
age: csv['age'],
height: csv['height'],
searchTerm: csv['searchTerm'],
);
}
class PeopleGetter {
static Future<List<People>> getPeopleSuggestions(String query) async {
try {
final String response =
await rootBundle.loadString('assets/data/people.csv');
final List people = CsvToListConverter(response);
return people
.map((csv) => People.fromCSV(csv))
.where((people) {
final searchTermLower = people.searchTerm.toLowerCase();
final queryLower = query.toLowerCase();
return searchTermLower.contains(queryLower);
}).toList();
} catch (e) {
print(e);
}
throw '';
}
}
Unfortunately, when I use this version within the search delegate, I get the error:
'type 'List<dynamic>' is not a subtype of type 'Map<String, dynamic>'.
I feel like I'll just have made a very simple error somewhere but at the moment, I just can't spot it. I would really appreciate any help correcting my code, to allow me to search with CSV data, instead of JSON data. Thanks!
It seems that your data types are not corresponding anymore:
You provide a List<dynamic> to a function that expects a Map<>
people.map((csv) => People.fromCSV(csv))
static People fromCSV(Map<String, dynamic> csv) => People(
name: csv['name'],
age: csv['age'],
height: csv['height'],
searchTerm: csv['searchTerm'],
);
Could you try rewriting your function from CSV to adapt to the new incoming data ? I'm not sure what is the data you get but maybe something like that ?
static People fromCSV(List<dynamic> csv) => People(
name: csv[0] ?? "",
age: csv[1] ?? -1,
height: csv[2] ?? -1,
searchTerm: csv[3] ?? "",
);
EDIT (fixing the few remaining bugs)
Updated CSV package version
Correctly retrieve the double from the csv
Set the delimiter parameter to separate two people in the CSV
class People {
final String name;
final double age;
final double height;
final String searchTerm;
People({
required this.name,
required this.age,
required this.height,
required this.searchTerm,
});
static People fromCSV(List<dynamic> csv) => People(
name: csv[0] ?? '',
age: double.parse(csv[1].toString()),
height: double.parse(csv[2].toString()),
searchTerm: csv[3] ?? '',
);
}
class PeopleGetter {
static Future<List<People>> getPeopleSuggestions(String query) async {
try {
final String response = await rootBundle.loadString('assets/data.csv');
final List<List<dynamic>> people =
CsvToListConverter().convert(response, eol: "\n");
return people.map((csv) => People.fromCSV(csv)).where((people) {
final searchTermLower = people.searchTerm.toLowerCase();
final queryLower = query.toLowerCase();
return searchTermLower.contains(queryLower);
}).toList();
} catch (e) {
print(e);
}
throw '';
}
}
I need to obtain a list of Articles(a custom object) from a realtime database in Firebase. I first decode my data from a json data type. Then I try to convert it into a list using this line of code:
List<Article> articles = List<Article>.from(articleResponse)
.map((Map model) => Article.fromJson(model))
.toList();
However, this gives a syntax error of "The argument type 'Article Function(Map<dynamic,dynamic>)' can't be assigned to the parameter type 'dynamic Function(Article)'." I have included the code I use to fetch an Article(the custom object) as well as the factory method for the class.
//Method to get articles
Future<List<Article>> fetchArticles() async {
final response = await http.get(
"https://some-server.firebaseio.com/some-url.json");
final articleResponse = json.decode(response.body);
List<Article> articles = List<Article>.from(articleResponse)
.map((Map model) => Article.fromJson(model))
.toList(); // Now we're looping over the response entries (maps of article info) to create Article instances
return articles;
}
\\Factory Method
factory Article.fromJson(Map<String, dynamic> json) {
return Article(
id: json['id'],
title: json['title'],
author: json['author'],
date: json['date'],
imageUrl: json['imageUrl'],
modalities: json['modalities'],
);
}
I make an example with something like a json response.
void main() {
//this is an example like a json response
List<Map<String, dynamic>> articleResponse = [
{
"id":"1",
"name":"test1"
},
{
"id":"2",
"name":"test2"
}
];
List<Article> articles = List<Article>.from(articleResponse.map((Map art)=>Article.fromJson(art)))
.toList();
print('${articles.length} articles in the list!! use to render de ui list');
}
class Article{
String id;
String name;
Article({this.id,this.name});
factory Article.fromJson(Map<String, dynamic> json) {
return Article(
id: json['id'],
name: json['name'],
);
}
}
basically you need to change your method to get articles with this.
//Method to get articles
Future<List<Article>> fetchArticles() async {
final response = await http.get(
"https://some-server.firebaseio.com/some-url.json");
final articleResponse = json.decode(response.body);
List<Article> articles = List<Article>.from(articleResponse.map((Map art)=>Article.fromJson(art)))
.toList(); // Now we're looping over the response entries (maps of article info) to create Article instances
return articles;
}
you can use JsonToDart
this is create a class for parse your complex json data
paste json and get class of model
you can overrride toString in your model like:
#override
String toString() {
return '{
id: $id,
title: $title,
author: $author,
date: $date,
imageUrl: $imageUrl,
modalities: $modalities
}';
}
and override toMap :
Map<String, dynamic> toMap() {
return <String, dynamic>{
'id': id,
'title': title,
'author': author,
'date': date,
'imageUrl': imageUrl,
'modalities': modalities,
};
}
and you can use serialization that. this can help you
Here am I again with another general question:
How can I persist my (nested) model structures from Dart/Flutter in ONE JSON-File on my File System?
My models look like this:
First, my subject model:
import './topic.dart';
class Subject {
String name;
int order;
bool isMajor;
List<Topic> topics;
Subject({this.name, this.order, this.isMajor, this.topics});
factory Subject.fromJSON(Map<String, dynamic> json) {
if (json != null) {
return Subject(
name: json['name'],
order: json['order'],
isMajor: json['isMajor'],
topics: List<Topic>.from(
json['topics'].map((topic) => Topic.fromJSON(topic))));
} else {
return null;
}
}
Map<String, dynamic> toJSON() {
return {
'name': name,
'order': order,
'isMajor': isMajor,
'topics': topics,
};
}
}
Now, the topic model:
import './content.dart';
class Topic {
String name;
int order;
List<Content> contents;
Topic({this.name, this.order, this.contents});
factory Topic.fromJSON(Map<String, dynamic> json) {
if (json != null) {
return Topic(
name: json['name'],
order: json['order'],
contents: List<Content>.from(
json['contents'].map((content) => Content.fromJSON(content))));
} else {
return null;
}
}
Map<String, dynamic> toJSON() {
return {
'name': name,
'order': order,
'contents': contents,
};
}
}
And lastly, the content model:
class Content {
String title;
String body;
int order;
bool isImportant;
Content({this.title, this.body, this.order, this.isImportant});
factory Content.fromJSON(Map<String, dynamic> json) {
if (json != null) {
return Content(
title: json['title'],
body: json['body'],
order: json['order'],
isImportant: json['isImportant']);
} else {
return null;
}
}
Map<String, dynamic> toJSON() {
return {
'title': title,
'body': body,
'order': order,
'isImportant': isImportant,
};
}
}
What I am interested in is the way you compile all the data into a JSON-String... OK?
If anyone has a bit of time and an idea, please feel free to answer!
Thank you for all the efforts!
Use the jsonEncode function to convert List or Map to Json strings:
Map<String, dynamic> json = {
'code' : 241,
};
String jsonString = jsonEncode(json);
In the Subject class, List<Topic> is not a supported type in json so you need to convert it to json strings:
Map<String, dynamic> toJSON() {
return {
'name': name,
'order': order,
'isMajor': isMajor,
'topics': topics
.map((topic) => jsonEncode(topic.toJSON()))
.toList(), // topics is now List<String>
};
}