so i have this http req payload, and i want to push it into an array, can someone help me?
The payload
{
"status":200,
"length":3,
"results":[
{
"_id":"60cd70b3fb9fe400117e8c6b",
"title":"Welcome to xxx",
"body":"Welcome to xx! We’re excited that everyone’s here and hope your ready for an epic weekend."
},
{
"_id":"60cd70b3fb9fe400117e8c6c",
"title":"Lunch Info",
"body":"Lunch is from our generous sponsors Lorem Ipsum! It will be served in the left atrium under the palm trees."
},
{
"_id":"60cd70b3fb9fe400117e8c6d",
"title":"Leash Dogs",
"body":"A friendly reminder that dogs must be leashed at all times, no matter how cute <3"
}
]
}
My Provider Code [UPDATED]
//So I've tried to debug on my own, and number 1 and number 2 is printed, while number 3 is not. I suspect its because of the way I handle extractedData.
class Announcements {
int? status;
int? length;
List<Results>? results;
Announcements(
{required this.status, required this.length, required this.results});
Announcements.fromJson(Map<String, dynamic> json) {
status = json['status'];
length = json['length'];
if (json['results'] != null) {
results = [];
json['results'].forEach((v) {
results!.add(new Results.fromJson(v));
});
}
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['status'] = this.status;
data['length'] = this.length;
if (this.results != null) {
data['results'] = this.results!.map((v) => v.toJson()).toList();
}
return data;
}
}
// so i've used your online converter json
class Results {
String? sId;
String? title;
String? body;
Results({required this.sId, required this.title, required this.body});
Results.fromJson(Map<String, dynamic> json) {
sId = json['_id'];
title = json['title'];
body = json['body'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['_id'] = this.sId;
data['title'] = this.title;
data['body'] = this.body;
return data;
}
}
class AnnouncementProvider with ChangeNotifier {
AnnouncementProvider(String? token, items);
List _items = [];
List get items {
return [..._items];
}
// List<Announcements> parseAnnouncement(String responseBody) {
// }
Future<List<Announcements>> fetchAnnouncements(String authToken) async {
//var url = Uri.https('api-staging.xxx.us.org', '/1.0/announcements');
final response = await http.get(
Uri.parse('https://api-staging.xxx.us.org/1.0/announcements'),
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json',
'Authorization': 'Bearer $authToken',
},
);
print(response.body);
final t = Announcements.fromJson(response.body as Map<String, dynamic>);
print(t.results);
return t.results;
}
}
What I need to know is, how do I return the list correctly, since the print(t.results) is actually not printed for some reason, so now it only shows "An error has occured" in my interface.
Thanks for helping!
Consider making a Dart Model object for the same, I would highly recommend you to do so because this is guaranteed serialization and type safe
For your case I used an imaginary name FoodItems for the type of data you received from your api endpoint
class FoodItems {
int status;
int length;
List<Results> results;
FoodItems({this.status, this.length, this.results});
FoodItems.fromJson(Map<String, dynamic> json) {
status = json['status'];
length = json['length'];
if (json['results'] != null) {
results = new List<Results>();
json['results'].forEach((v) {
results.add(new Results.fromJson(v));
});
}
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['status'] = this.status;
data['length'] = this.length;
if (this.results != null) {
data['results'] = this.results.map((v) => v.toJson()).toList();
}
return data;
}
}
class Results {
String sId;
String title;
String body;
Results({this.sId, this.title, this.body});
Results.fromJson(Map<String, dynamic> json) {
sId = json['_id'];
title = json['title'];
body = json['body'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['_id'] = this.sId;
data['title'] = this.title;
data['body'] = this.body;
return data;
}
}
Now you can easily cast your response.body to the FoodItems class using fromJson method and then get the desired list of Results and then iterate over it
In my honest opinion, it makes it much simpler this way
Note: I would highly recommend reading the following
This is a nice article from the Flutter Developers themselves
Android Studio Plugin to do the serialization for you
Online converter
Related
I have the following 4 classes. In this, only the ProductGroup is saved, ProductVariant, ProductSize and ProductColor are not stored. Please help me with this.
product_group.dart
#Collection()
class ProductGroup {
late Id id;
#Index(caseSensitive: false)
late String productGroupName;
final productVariants = IsarLinks<ProductVariant>();
ProductGroup();
ProductGroup.fromJson(Map<String, dynamic> json) {
id = json['Id'];
productGroupName = json['PG'];
if (json['Ps'] != null) {
json['Ps'].forEach((variant) {
productVariants.add(ProductVariant.fromJson(variant));
});
}
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = <String, dynamic>{};
data['Id'] = id;
data['PG'] = productGroupName;
data['Ps'] = productVariants.map((variant) => variant.toJson()).toList();
return data;
}
}
product_variant.dart
#Collection()
class ProductVariant {
late Id id;
late String variantName;
final productSizes = IsarLinks<ProductSize>();
ProductVariant();
ProductVariant.fromJson(Map<String, dynamic> json) {
id = json['Id'];
variantName = json['St'];
if (json['Ss'] != null) {
json['Ss'].forEach((v) {
productSizes.add(ProductSize.fromJson(v));
});
}
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = <String, dynamic>{};
data['Id'] = id;
data['St'] = variantName;
data['Ss'] = productSizes.map((v) => v.toJson()).toList();
return data;
}
}
product_size.dart
#Collection()
class ProductSize {
late Id id;
late String size;
final productColors = IsarLinks<ProductColor>();
ProductSize();
ProductSize.fromJson(Map<String, dynamic> json) {
id = json['Id'];
size = json['S'];
if (json['Cs'] != null) {
json['Cs'].forEach((v) {
productColors.add(ProductColor.fromJson(v));
});
}
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = <String, dynamic>{};
data['Id'] = id;
data['S'] = size;
data['Cs'] = productColors.map((color) => color.toJson()).toList();
return data;
}
}
product_color.dart
#Collection()
class ProductColor {
late Id id;
late String colorName;
late String colorHexCode;
ProductColor();
ProductColor.fromJson(Map<String, dynamic> json) {
id = json['Id'];
colorName = json['C'];
colorHexCode = json['CC'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = <String, dynamic>{};
data['Id'] = id;
data['C'] = colorName;
data['CC'] = colorHexCode;
return data;
}
}
I am parsing the json and saving it in Isar
convertJsonToIsar() async {
try {
// For testing purposes, loading Json from assets, in Prod, Json will be fetched from server
final String response = await rootBundle.loadString('assets/pr_dump.json');
final data = await json.decode(response);
List<ProductGroup> productGroupList = [];
data.forEach((item) {
productGroupList.add(ProductGroup.fromJson(item));
});
Isar _isar = getIsar();
_isar.writeTxnSync(() {
_isar.productGroups.putAllSync(productGroupList, saveLinks: true);
});
} catch (e) {
// Handle Error
print('Caught Error');
print(e.toString());
return 0;
}
}
Only the ProductGroup is stored, ProductVariant, ProductSize and ProductColor are not stored. Please help me with this.
This is my model class and I am trying to get all the data but getting error and don't know why.
HomePageModel homePageModelFromJson(String str) => HomePageModel.fromJson(json.decode(str));
String homePageModelToJson(HomePageModel data) => json.encode(data.toJson());
class HomePageModel with ChangeNotifier {
HomePageModel({
this.data,
});
List<Datum>? data;
factory HomePageModel.fromJson(Map<String, dynamic> json) => HomePageModel(
data: List<Datum>.from(json["data"]!.map((x) => Datum.fromJson(x))),
);
Map<String, dynamic> toJson() => {
"data": List<dynamic>.from(data!.map((x) => x.toJson())),
};
}
class Datum {
Datum({
this.schoolid,
this.name,
this.logo,
this.address,
this.contact,
this.principalname,
this.principalcontact,
this.slogan,
this.webAddress,
this.description,
this.email,
this.pan,
this.establishedYear,
});
String? schoolid;
String? name;
String? logo;
String? address;
String? contact;
String? principalname;
String? principalcontact;
String? slogan;
String? webAddress;
String? description;
String? email;
String? pan;
int? establishedYear;
factory Datum.fromJson(Map<String, dynamic> json) => Datum(
schoolid: json["schoolid"],
name: json["name"],
logo: json["logo"],
address: json["address"],
contact: json["contact"],
principalname: json["principalname"],
principalcontact: json["principalcontact"],
slogan: json["slogan"],
webAddress: json["web_address"] == null ? null : json["web_address"],
description: json["description"] == null ? null : json["description"],
email: json["email"],
pan: json["pan"],
establishedYear: json["established_year"],
);
Map<String, dynamic> toJson() => {
"schoolid": schoolid,
"name": name,
"logo": logo,
"address": address,
"contact": contact,
"principalname": principalname,
"principalcontact": principalcontact,
"slogan": slogan,
"web_address": webAddress == null ? null : webAddress,
"description": description == null ? null : description,
"email": email,
"pan": pan,
"established_year": establishedYear,
};
}
This is how I am trying to fetch data:
class HomePageModels with ChangeNotifier{
List<HomePageModel> _hItem = [];
List<HomePageModel> get hItem{
return [..._hItem];
}
Future<void> getHomeData(BuildContext context) async{
const url = "https://shikshyasoftware.com.np/CoreApplicationandAPIService-4617993073/api/school";
try{
// EasyLoading.show(status: 'Loading...');
final response = await http.get(Uri.parse(url));
final extractedData = json.decode(response.body);
List<HomePageModel> loadedHomeData = [];
if(extractedData == null){
return;
}
if(response.statusCode == 200){
print(extractedData);
}
extractedData.forEach((element){
loadedHomeData.add(HomePageModel.fromJson(element));
});
_hItem = loadedHomeData;
// EasyLoading.showSuccess("data fetched sucessfull");
notifyListeners();
}catch(e){
rethrow;
}
}
}
But I am getting error:
[ERROR:flutter/lib/ui/ui_dart_state.cc(209)] Unhandled Exception: type '(dynamic) => Null' is not a subtype of type '(String, dynamic) => void' of 'f'
The problem is the way you are trying to parse the data, you don't need to loop over every element to parse it, in your model just make it return a list type like this,
class HomePageModel with ChangeNotifier {
List<Datum>? data;
HomePageModel({this.data});
HomePageModel.fromJson(Map<String, dynamic> json) {
if (json['data'] != null) {
data = <Datum>[];
json['data'].forEach((v) {
data!.add(new Datum.fromJson(v));
});
}
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
if (this.data != null) {
data['data'] = this.data!.map((v) => v.toJson()).toList();
}
return data;
}
}
class Datum {
Datum({
this.schoolid,
this.name,
this.logo,
this.address,
this.contact,
this.principalname,
this.principalcontact,
this.slogan,
this.webAddress,
this.description,
this.email,
this.pan,
this.establishedYear,
});
String? schoolid;
String? name;
String? logo;
String? address;
String? contact;
String? principalname;
String? principalcontact;
String? slogan;
String? webAddress;
String? description;
String? email;
String? pan;
int? establishedYear;
Datum.fromJson(Map<String, dynamic> json) {
schoolid = json["schoolid"];
name = json["name"];
logo = json["logo"];
address = json["address"];
contact = json["contact"];
principalname = json["principalname"];
principalcontact = json["principalcontact"];
slogan = json["slogan"];
webAddress = json["web_address"];
description = json["description"];
email = json["email"];
pan = json["pan"];
establishedYear = json["established_year"];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['schoolid'] = this.schoolid;
data['name'] = this.name;
data['logo'] = this.logo;
data['address'] = this.address;
data['contact'] = this.contact;
data['principalname'] = this.principalname;
data['principalcontact'] = this.principalcontact;
data['slogan'] = this.slogan;
data['web_address'] = this.webAddress;
data['description'] = this.description;
data['email'] = this.email;
data['pan'] = this.pan;
data['established_year'] = this.establishedYear;
return data;
}
}
and in your view model you can just parse the extracted data from response.body like this,
class HomePageModels with ChangeNotifier {
HomePageModel? _hItem;
HomePageModel get hItem {
return _hItem!;
}
Future<void> getHomeData(BuildContext context) async {
const url =
"https://shikshyasoftware.com.np/CoreApplicationandAPIService-
4617993073/api/school";
try {
// EasyLoading.show(status: 'Loading...');
final response = await http.get(Uri.parse(url));
final extractedData = json.decode(response.body);
if (extractedData == null) {
return;
}
if (response.statusCode == 200) {
print(extractedData);
}
HomePageModel loadedHomeData =
HomePageModel.fromJson(extractedData);
_hItem = loadedHomeData;
// EasyLoading.showSuccess("data fetched sucessfull");
notifyListeners();
} catch (e) {
rethrow;
}
}
}
getHomeData(BuildContext context) async {
const url =
"https://shikshyasoftware.com.np/CoreApplicationandAPIService-4617993073/api/school";
try {
// EasyLoading.show(status: 'Loading...');
final response = await http.get(Uri.parse(url));
if (response.statusCode == 200) {
final extractedData = json.decode(response.body);
List loadedHomeData = extractedData;
_hItem = loadedHomeData.map((e) => HomePageModel.fromJson(e)).toList();
}
notifyListeners();
return _hItem;
} catch (e) {
rethrow;
}
}
My PokemonModel and Results class, i wan't return a List
class PokemonModel {
int count;
String next;
String previous;
List<Results> results;
PokemonModel({this.count, this.next, this.previous, this.results});
PokemonModel.fromJson(Map<String, dynamic> json) {
count = json['count'];
next = json['next'];
previous = json['previous'];
if (json['results'] != null) {
results = [];
json['results'].forEach((v) {
results.add(new Results.fromJson(v));
});
}
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['count'] = this.count;
data['next'] = this.next;
data['previous'] = this.previous;
if (this.results != null) {
data['results'] = this.results.map((v) => v.toJson()).toList();
}
return data;
}
}
class Results {
String name;
String url;
Results({this.name, this.url});
Results.fromJson(Map<String, dynamic> json) {
name = json['name'];
url = json['url'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['name'] = this.name;
data['url'] = this.url;
return data;
}
}
I try use this on repository, i'll need ['next'], ['previous'] and results data to use in widgets but i cannot convert the data to a list of PokemonModel.
That's my current repository where i try get data.
class PokemonRepository implements IPokemonRepository {
Dio _dio;
final String url = 'https://pokeapi.co/api/v2/pokemon/';
PokemonRepository([Dio dio]) : _dio = dio ?? Dio();
#override
Future<List<PokemonModel>> getPokemons() async {
final response = await _dio.get(url);
final poke = PokemonModel.fromJson(response.data);
//how parse and return a list of pokemonmodel?
}
}
There are a couple of ways you can do it.
// method 1 (declarative/functional programming)
final List<PokemonModel> myList = response
.map<PokemonModel>((item) => PokemonModel.fromJson(item))
.toList();
return myList;
or
// method 2 (imperative)
final myList2 = <PokemonModel>[];
for (final Map<String, dynamic> item in response) {
myList2.add(PokemonModel.fromJson(item));
}
return myList2;
I've seen it done both ways. Both return the same result.
I have this data format
message": [
{
"id": 15989,
"title": "xxx",
"body": "xxx",
"type": "abc",
"data_hash": "{\"id\":\"3098\",\"number\":1}",
}, .....]
If I write like this
print(message['data']['type']);
I can get abc, but if I write print(message['data']['data_hash']);, I get invalid arguments error. Why?
I want to get the number in data_hash.
This is the full code
_firebaseMessaging.configure(
onMessage: (Map<String, dynamic> message) async {
print("===== onMessage ====");
try {
print(message['data']['data_hash']);
} catch (e) {
print(e.toString());
}
});
data_hash row is a json. So you need to decode that row for use.
final data_hash_map = jsonDecode(message['data']['data_hash']);
print(data_hash_map); // { "id": 3098, "number": 1 }
print(data_hash_map["number"]); // for number
Decode your json as below
Map<String, dynamic> jsonData = jsonDecode(message)
I recommend to create a class to predefine the object as followed:
class Message {
int id;
String title;
String body;
String type;
DataHash dataHash;
message({this.id, this.title, this.body, this.type, this.dataHash});
Message.fromJson(Map<String, dynamic> json) {
id = json['id'];
title = json['title'];
body = json['body'];
type = json['type'];
dataHash = json['data_hash'] != null
? new DataHash.fromJson(json['data_hash'])
: null;
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['id'] = this.id;
data['title'] = this.title;
data['body'] = this.body;
data['type'] = this.type;
if (this.dataHash != null) {
data['data_hash'] = this.dataHash.toJson();
}
return data;
}
}
class DataHash {
String id;
String number;
DataHash({this.id, this.number});
DataHash.fromJson(Map<String, dynamic> json) {
id = json['id'];
number = json['number'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['id'] = this.id;
data['number'] = this.number;
return data;
}
}
You can call Message.fromJson(data) to decode.
Messsage message = Message.fromJson(data);
print(message.dataHash.number);
I hope this will work correctly
class _HomeState extends State<Mytimeoff> {
List<Map> list = [];
Map leaveRoot ={};
void getList() async {
var data = await http
.get('https:your api link');
leaveRoot = Map.from(json.decode(data.body));
setState(() {
for (Map js in leaveRoot['leavetype']) {
list.add(js);
}
});
print(jsonData);
}
#override
void initState() {
super.initState();
getList();
}
#override
Widget build(BuildContext context) {
return Scaffold();
}
}
I have following Model
product_model.dart
class ProductModel {
String status;
String message;
List<Results> results;
ProductModel({this.status, this.message, this.results});
ProductModel.fromJson(Map<String, dynamic> json) {
status = json['status'];
message = json['message'];
if (json['data'] != null) {
results = new List<Results>();
json['data'].forEach((v) {
results.add(new Results.fromJson(v));
});
}
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['status'] = this.status;
data['message'] = this.message;
if (this.results != null) {
data['data'] = this.results.map((v) => v.toJson()).toList();
}
return data;
}
}
class Results {
String id;
String productCode;
String category;
String title;
String isActive;
Results(
{this.id,
this.productCode,
this.category,
this.title,
this.isActive,
});
Results.fromJson(Map<String, dynamic> json) {
id = json['id'];
productCode = json['product_code'];
category = json['category'];
title = json['title'];
isActive = json['is_active'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['id'] = this.id;
data['product_code'] = this.productCode;
data['title'] = this.title;
data['category'] = this.category;
data['is_active'] = this.isActive;
return data;
}
}
I have a functionality to save products to favorites. The favorites will be saved as json in a file.
import 'package:example/utils/favstorage.dart';
import 'package:example/models/product_model.dart';
class FavoriteProducts {
FavoritesStorage storage = FavoritesStorage();
List<ProductModel> favorites = [];
Future addFavorite(ProductModel products) async {
favorites.add(products);
await storage.writeFavorites(favorites);
}
}
I want to add product to favorites only if its not there. How can I update the addFavorite method so that if particular id doesnot exist then only proceed adding to favorites.
I am new to flutter. Can anybody help me on this??
You can use and indexWhere to search your list for an item with the same id, like this:
Future addFavorite(ProductModel products) async {
if(favorites.indexWhere((listProduct) => listProduct.id == products.id) == -1){
favorites.add(products);
await storage.writeFavorites(favorites);
}
}
-1 means there was no item, if there was the item it would have returned it from the list.
Understanding your model:
ProductModel has List
Results has id.
How to see if provided ProductModel can be added to favorite:
Take favorites list and look in List.
in each product model liik in List.
for each Results check if there id is same as any Results in List of provided ProductModel to the method.
If every thing is false, add ProductModel to favorite.
Following is the code for your reference:
Future addFavorite(ProductModel products) async {
bool containsId = favorites.any((ProductModel model){
return model.results.any((Results result){
return products.results.any((Results resultInProducts) => resultInProducts.id == result.id);
});
});
if(!containsId){
favorites.add(products);
await storage.writeFavorites(favorites);
}
}
I hope this helps, in case of any doubt please comment. If this answer helps you then please accept and up-vote the answer.