I am fetching data like this
Future<List> dosomestuff() async {
http.Response res = await http.get(
'http://retailapi.airtechsolutions.pk/api/menu/2112',
);
Map<String, dynamic> map = json.decode(res.body);
print(map);
}
Its showing data like this
{
"Categories": [{
"ID": 1064,
"Name": "Pizza",
"Subcategories": [{
"ID": 87,
"CategoryID": 1064,
"CategoryName": "Pizza",
"Items": [{
"ID": 1195,
"Name": "Fajita Pizza (S)"
},
{
"ID": 1196,
"Name": "Fajita Pizza (M)"
},
{
"ID": 1197,
"Name": "Fajita Pizza (L)"
}
]
},
{
"ID": 87,
"CategoryID": 1064,
"CategoryName": "Pizza",
"Items": [{
"ID": 1195,
"Name": "Fajita Pizza (S)"
},
{
"ID": 1196,
"Name": "Fajita Pizza (M)"
},
{
"ID": 1197,
"Name": "Fajita Pizza (L)"
}
]
}
]
},
{
"ID": 1064,
"Name": "Pizza",
"Subcategories": [{
"ID": 87,
"CategoryID": 1064,
"CategoryName": "Pizza",
"Items": [{
"ID": 1195,
"Name": "Fajita Pizza (S)"
},
{
"ID": 1196,
"Name": "Fajita Pizza (M)"
},
{
"ID": 1197,
"Name": "Fajita Pizza (L)"
}
]
}]
},
{
"ID": 1084,
"Name": "beverages",
"Description": null,
"Image": null,
"StatusID": 1,
"LocationID": 2112,
"Subcategories": []
}
],
"description": "Success",
"status": 1
}
What i need to do know is show items of all arrays. Mean in above data there are 2 arrays in subcategories and in 1 array there are 3 items. I need to merge all items of array 1 and 2 so it can total 6.
Expecting output
{ "Items": [
{
"ID": 1195,
"SubCategoryID": 87,
"Name": "Fajita Pizza (S)",
},
{
"ID": 1196,
"SubCategoryID": 87,
"Name": "Fajita Pizza (M)",
},
{
"ID": 1197,
"SubCategoryID": 87,
"Name": "Fajita Pizza (L)",
},
{
"ID": 1195,
"SubCategoryID": 87,
"Name": "Fajita Pizza (S)",
},
{
"ID": 1196,
"SubCategoryID": 87,
"Name": "Fajita Pizza (M)",
},
{
"ID": 1197,
"SubCategoryID": 87,
"Name": "Fajita Pizza (L)",
}
]
}
I don't know if I understand what you want to do but you can try the addAll function
fetchedList = [a, b, 2, 3];
myList = [4, 5, c];
fetchedList.addAll(myList);
print(fetchedList);
// [a, b, 2, 3, 4, 5, c]
hope these steps help you:
Create a new empty map
Loop in your map data['Categories']['Subcategories']
Put each element in your new map
You can use forEach to split the json data layer by layer
var items = {'Items':[]};
if(map['Categories'] != null){
map['Categories'].forEach((category){
if(category['Subcategories'] != null){
category['Subcategories'].forEach((subcategory){
items['Items'].addAll(subcategory['Items']);
});
}
});
}
print(items);
dynamic data = {
"Categories": [
{
"ID": 1064,
"Name": "Pizza",
"Subcategories": [
{
"ID": 87,
"CategoryID": 1064,
"CategoryName": "Pizza",
"Items": [
{"ID": 1195, "Name": "Fajita Pizza (S)"},
{"ID": 1196, "Name": "Fajita Pizza (M)"},
{"ID": 1197, "Name": "Fajita Pizza (L)"}
]
},
{
"ID": 87,
"CategoryID": 1064,
"CategoryName": "Pizza",
"Items": [
{"ID": 1195, "Name": "Fajita Pizza (S)"},
{"ID": 1196, "Name": "Fajita Pizza (M)"},
{"ID": 1197, "Name": "Fajita Pizza (L)"}
]
}
]
},
{
"ID": 1064,
"Name": "Pizza",
"Subcategories": [
{
"ID": 87,
"CategoryID": 1064,
"CategoryName": "Pizza",
"Items": [
{"ID": 1195, "Name": "Fajita Pizza (S)"},
{"ID": 1196, "Name": "Fajita Pizza (M)"},
{"ID": 1197, "Name": "Fajita Pizza (L)"}
]
}
]
},
{
"ID": 1084,
"Name": "beverages",
"Description": null,
"Image": null,
"StatusID": 1,
"LocationID": 2112,
"Subcategories": []
},
null
],
"description": "Success",
"status": 1
};
var items = List();
var categories = data["Categories"];
categories.forEach((element) {
if (element == null) return;
List subCategories = element['Subcategories'];
subCategories.forEach((element) {
items.add(element["Items"]);
});
});
items = items.expand((element) => element).toList();
print(items);
Related
I want to modify color and title with same data for specified items with this keys {0024dd81-db96-4a87-863b-e6ca9dd69d91,0024dd81-db96-4a87-863b-e6ca9dd69d92,0024dd81-db96-4a87-863b-e6ca9dd69d93} in one query the result must be like this all in one query
result must be like this
{
"designation": "test"
"items": {
"0024dd81-db96-4a87-863b-e6ca9dd69d90": {
"id": 71,
"color": "#FFFFFF",
"title": "item1",
},
"0024dd81-db96-4a87-863b-e6ca9dd69d91": {
"id": 72,
"color": "#FFFFFF",
"title": "item2",
},
"0024dd81-db96-4a87-863b-e6ca9dd69d92": {
"id": 73,
"color": "#FFFFFF",
"title": "item3",
},
"0024dd81-db96-4a87-863b-e6ca9dd69d93": {
"id": 74,
"color": "#FFFFFF",
"title": "item4",
}
}
}
{
"designation": "test"
"items": {
"items": {
"0024dd81-db96-4a87-863b-e6ca9dd69d90": {
"id": 71,
"color": "#FFFFFF",
"title": "item1",
},
"0024dd81-db96-4a87-863b-e6ca9dd69d91": {
"id": 72,
"color": "#FFFFFF",
"title": "updated",
},
"0024dd81-db96-4a87-863b-e6ca9dd69d92": {
"id": 73,
"color": "#FFFFFF",
"title": "updated",
},
"0024dd81-db96-4a87-863b-e6ca9dd69d93": {
"id": 74,
"color": "#FFFFFF",
"title": "updated",
}
}
}
I am fetching data from an api, the output of the api is like this:
{
"Categories": [{
"ID": 1064,
"Name": "Pizza",
"Subcategories": [{
"ID": 87,
"CategoryID": 1064,
"CategoryName": "Pizza",
"Items": [{
"ID": 1195,
"Name": "Fajita Pizza (S)"
"IsFeatured": true,
},
{
"ID": 1196,
"Name": "Fajita Pizza (M)"
},
{
"ID": 1197,
"Name": "Fajita Pizza (L)"
}
]
},
{
"ID": 87,
"CategoryID": 1064,
"CategoryName": "Pizza",
"Items": [{
"ID": 1195,
"Name": "Fajita Pizza (S)"
},
{
"ID": 1196,
"Name": "Fajita Pizza (M)"
},
{
"ID": 1197,
"Name": "Fajita Pizza (L)"
}
]
}
]
},
{
"ID": 1064,
"Name": "Pizza",
"Subcategories": [{
"ID": 87,
"CategoryID": 1064,
"CategoryName": "Pizza",
"Items": [{
"ID": 1195,
"Name": "Fajita Pizza (S)"
"IsFeatured": true,
},
{
"ID": 1196,
"Name": "Fajita Pizza (M)"
},
{
"ID": 1197,
"Name": "Fajita Pizza (L)"
}
]
}]
},
{
"ID": 1084,
"Name": "beverages",
"Description": null,
"Image": null,
"StatusID": 1,
"LocationID": 2112,
"Subcategories": []
}
],
"description": "Success",
"status": 1
}
By foreach loop i am putting all items arrays in one array like this.
data.forEach((category) {
if (category['Subcategories'] != null) {
category['Subcategories'].forEach((subcategory) {
items['Items'].addAll(subcategory['Items']);
});
}
});
its working also fine now i need to do this to the Items which have "IsFeatured": true, all items array dont have IsFeatured in array only some have. So what i need to do is just add those Items which have IsFeatured True.
You could have a look at the more functional approaches to accomplish what you are doing. Especially the map and where functions on Dart's Iterable.
Before calling forEach in your inner loop you can call where. This takes a function (like forEach does) that returns either true or false. If the condition is true` the item remains in the list, otherwise it is filtered out.
Something like this:
category['Subcategories']
.where((subcategory) => subcategory.isFeatured)
.forEach((subcategory) {
items['Items'].addAll(subcategory['Items']);
});
Edit:
I didn't realize that the property in question is actually one level down, i.e. part of the item.
So combining this with a null-safe access we might get something like:
data.forEach((category) {
category['Subcategories']?.forEach((subcategory) {
items['Items'].addAll(subcategory['Items'].where((s) => s['IsFeatured'] as bool));
});
});
You might have to tweak a few things depending on your actual data model and what assumptions you can make about the presence of values. In the example code I assume that IsFeatured is never null. That might not be the case, so look out for errors there.
I have data like this
{
"Categories": [{
"ID": 1064,
"Name": "Pizza",
"Subcategories": [{
"ID": 87,
"CategoryID": 1064,
"CategoryName": "Pizza",
"Items": [{
"ID": 1195,
"Name": "Fajita Pizza (S)"
"IsFeatured": true,
},
{
"ID": 1196,
"Name": "Fajita Pizza (M)"
},
{
"ID": 1197,
"Name": "Fajita Pizza (L)"
}
]
},
{
"ID": 87,
"CategoryID": 1064,
"CategoryName": "Pizza",
"Items": [{
"ID": 1195,
"Name": "Fajita Pizza (S)"
},
{
"ID": 1196,
"Name": "Fajita Pizza (M)"
},
{
"ID": 1197,
"Name": "Fajita Pizza (L)"
}
]
}
]
},
{
"ID": 1064,
"Name": "Pizza",
"Subcategories": [{
"ID": 87,
"CategoryID": 1064,
"CategoryName": "Pizza",
"Items": [{
"ID": 1195,
"Name": "Fajita Pizza (S)"
"IsFeatured": true,
},
{
"ID": 1196,
"Name": "Fajita Pizza (M)"
},
{
"ID": 1197,
"Name": "Fajita Pizza (L)"
}
]
}]
},
{
"ID": 1084,
"Name": "beverages",
"Description": null,
"Image": null,
"StatusID": 1,
"LocationID": 2112,
"Subcategories": []
}
],
"description": "Success",
"status": 1
}
What I need to do is add all Items which are in Subcategories in single array. and its working fine its working like this
Future<List> dosomestuff() async {
print(WishList.wishlistArray);
http.Response res = await http.get(
'http://retailapi.airtechsolutions.pk/api/menu/2112',
);
Map<String, dynamic> map = json.decode(res.body);
if (map['description'] == "Success") {
print('show kr ');
List<dynamic> data = map["Categories"];
data.forEach((category) {
if (category['Subcategories'] != null) {
category['Subcategories'].forEach((subcategory) {
items['Items'].addAll(
subcategory['Items']
);
});
}
});
}
}
Now there is one issue now I need to add only those items whose ID is in my other array.
Othere array is this WishList.wishlistArray the data is in array look like this
[1217, 1216, 1195, 1196, 1197]
What I need to is I need to add those Items only whose Id is in this array
You can use .where() method of List to filter items by ID.
Try this code:
final allowedItemIds = [1217, 1216, 1195, 1196, 1197];
List<dynamic> data = map["Categories"];
data.forEach((category) {
if (category['Subcategories'] != null) {
category['Subcategories'].forEach((subcategory) {
final itemsToAdd = subcategory['Items'];
final filteredItemsToAdd =
itemsToAdd.where((item) => allowedItemIds.contains(item['ID']));
items['Items'].addAll(filteredItemsToAdd);
});
}
},
);
I am fetching data from api something like this
{
"Categories": [{
"ID": 1064,
"Name": "Pizza",
"Subcategories": [{
"ID": 87,
"CategoryID": 1064,
"CategoryName": "Pizza",
"Items": [{
"ID": 1195,
"Name": "Fajita Pizza (S)"
"IsFeatured": true
},
{
"ID": 1196,
"Name": "Fajita Pizza (M)"
"IsFeatured": true
},
{
"ID": 1197,
"Name": "Fajita Pizza (L)",
"IsFeatured": false,
}
]
},
{
"ID": 87,
"CategoryID": 1064,
"CategoryName": "Pizza",
"Items": [{
"ID": 1195,
"Name": "Fajita Pizza (S)"
},
{
"ID": 1196,
"Name": "Fajita Pizza (M)"
},
{
"ID": 1197,
"Name": "Fajita Pizza (L)"
}
]
}
]
},
{
"ID": 1064,
"Name": "Pizza",
"Subcategories": [{
"ID": 87,
"CategoryID": 1064,
"CategoryName": "Pizza",
"Items": [{
"ID": 1195,
"Name": "Fajita Pizza (S)"
"IsFeatured": true,
},
{
"ID": 1196,
"Name": "Fajita Pizza (M)"
},
{
"ID": 1197,
"Name": "Fajita Pizza (L)"
}
]
}]
},
{
"ID": 1084,
"Name": "beverages",
"Description": null,
"Image": null,
"StatusID": 1,
"LocationID": 2112,
"Subcategories": []
}
],
"description": "Success",
"status": 1
}
What i need to do is add items in an array which is also working. But i need to do is i need to add those items which have "IsFeatured": true
I got answer on my other post which is this
data.forEach((category) {
if (category['Subcategories'] != null) {
category['Subcategories']
.where((subcategory) => subcategory.isFeatured)
.forEach((subcategory) {
featured['Featured'].addAll(subcategory['Items']);
});
}
});
print(featured);
Its showing this error in this answer
Unhandled Exception: type '(dynamic) => dynamic' is not a subtype of type '(dynamic) => bool' of 'test'
Adding my whole function code
Future<List> dosomestuff() async {
http.Response res = await http.get(
'http://retailapi.airtechsolutions.pk/api/menu/2112',
);
Map<String, dynamic> map = json.decode(res.body);
if (map['description'] == "Success") {
print('show kr ');
List<dynamic> data = map["Categories"];
data.forEach((category) {
if (category['Subcategories'] != null) {
category['Subcategories'].forEach((subcategory) {
items['Items'].addAll(subcategory['Items']);
});
}
});
data.forEach((category) {
if (category['Subcategories'] != null) {
category['Subcategories'].forEach((subcategory) {
subcategory['Items'].forEach((item) {
if (item['IsfeatureProduct'] ?? false) {
featureProduct.add(item);
}
});
});
}
});
print('featureProduct');
print(featureProduct);
print(items["Items"].length);
print(map["Categories"].length);
print(map["Categories"]);
cat['Cat'].addAll(map['Categories']);
print(cat);
setState(() {
show = true;
});
}
}
this adds all the featured items to featured list
main(List<String> args) {
List data = api['Categories'];
var featured = [];
data.forEach((category) {
if (category['Subcategories'] != null) {
category['Subcategories'].forEach((subcategory) {
subcategory['Items'].forEach((item) {
if (item['IsFeatured'] ?? false) {
featured.add(item);
}
});
});
}
});
print(featured);
}
const api = {
"Categories": [{
"ID": 1064,
"Name": "Pizza",
"Subcategories": [{
"ID": 87,
"CategoryID": 1064,
"CategoryName": "Pizza",
"Items": [{
"ID": 1195,
"Name": "Fajita Pizza (S)"
"IsFeatured": true
},
{
"ID": 1196,
"Name": "Fajita Pizza (M)"
"IsFeatured": true
},
{
"ID": 1197,
"Name": "Fajita Pizza (L)",
"IsFeatured": false,
}
]
},
{
"ID": 87,
"CategoryID": 1064,
"CategoryName": "Pizza",
"Items": [{
"ID": 1195,
"Name": "Fajita Pizza (S)"
},
{
"ID": 1196,
"Name": "Fajita Pizza (M)"
},
{
"ID": 1197,
"Name": "Fajita Pizza (L)"
}
]
}
]
},
{
"ID": 1064,
"Name": "Pizza",
"Subcategories": [{
"ID": 87,
"CategoryID": 1064,
"CategoryName": "Pizza",
"Items": [{
"ID": 1195,
"Name": "Fajita Pizza (S)"
"IsFeatured": true,
},
{
"ID": 1196,
"Name": "Fajita Pizza (M)"
},
{
"ID": 1197,
"Name": "Fajita Pizza (L)"
}
]
}]
},
{
"ID": 1084,
"Name": "beverages",
"Description": null,
"Image": null,
"StatusID": 1,
"LocationID": 2112,
"Subcategories": []
}
],
"description": "Success",
"status": 1
};
output:
[{ID: 1195, Name: Fajita Pizza (S), IsFeatured: true}, {ID: 1196, Name: Fajita Pizza (M), IsFeatured: true}, {ID: 1195, Name: Fajita Pizza (S), IsFeatured: true}]
There are 3 master collection of category , subcategory and criteria each, i will be building framework with any possible combination of category , subcategory and criteria which will be stored as below-
framework document is added below having list of criteriaconfig as embedded object which further have single object of category , subcategory and criteria. you can refer criteriaconfig as link table that u call in mysql.
[
{
"id": "592bc3059f3ad715002b2331",
"name": "Framework1",
"description": "framework 1 for testing",
"criteriaConfigs": [
{
"id": "592bc3059f3ad715002b232f",
"category": {
"id": "591c2f5faa187956b2d0fb39",
"name": "category1",
"description": "category1",
"deleted": false,
"createdDate": 1495019359558
},
"subCategory": {
"id": "591c2f5faa187956b2d0fb83",
"name": "subCat1",
"description": "subCat1"
},
"criteria": {
"id": "591c2f5faa187956b2d0fbad",
"name": "criteria1",
"measure": "Action"
}
},
{
"id": "592bc3059f3ad715002b232e",
"category": {
"id": "591c2f5faa187956b2d0fb37",
"name": "Process",
"description": "Enagagement"
},
"subCategory": {
"id": "591c2f5faa187956b2d0fb81",
"name": "COMM / BRANDING",
"description": "COMM / BRANDING"
},
"criteria": {
"id": "591c2f5faa187956b2d0fba9",
"name": "Company representative forgets about customer on hold",
"measure": ""
}
} ]
},
{
"id": "592bc3059f3ad715002b2332",
"name": "Framework2",
"description": "framework 2 for testing",
"criteriaConfigs": [
{
"id": "592bc3059f3ad715002b232f",
"category": {
"id": "591c2f5faa187956b2d0fb39",
"name": "category1",
"description": "category1"
},
"subCategory": {
"id": "591c2f5faa187956b2d0fb83",
"name": "subCat1",
"description": "subCat1"
},
"criteria": {
"id": "591c2f5faa187956b2d0fbad",
"name": "criteria1",
"measure": "Action"
}
}
]
}
]
i need a view containing framework that will contain all list of category and inside category there will be list of added subcategory and inside subcategory will have list of criteria for single framework.
expected result -
[
{
"id": "f1",
"name": "Framework1",
"description": "framework 1 for testing",
"categories": [
{
"id": "c2",
"name": "category2",
"description": "category2",
"subCategories": [
{
"id": "sb1",
"name": "subCat1",
"description": "subCat1",
"criterias": [
{
"id": "cr1",
"name": "criteria1",
"measure": "Action"
},
{
"id": "cr2",
"name": "criteria2",
"measure": "Action"
},
{
"id": "cr3",
"name": "criteria3",
"measure": "Action"
}]
},
{
"id": "sb2",
"name": "subCat2",
"description": "subCat2",
"criterias": [
{
"id": "cr1",
"name": "criteria1",
"measure": "Action"
},
{
"id": "cr4",
"name": "criteria4",
"measure": "Action"
}]
}]
},
{
"id": "c1",
"name": "category1",
"description": "category1",
"subCategories": [
{
"id": "sb3",
"name": "subCat3",
"description": "subCat3",
"criterias": [
{
"id": "cr1",
"name": "criteria1",
"measure": "Action"
},
{
"id": "cr2",
"name": "criteria2",
"measure": "Action"
}
]},
{
"id": "sb2",
"name": "subCat2",
"description": "subCat2",
"criterias": [
{
"id": "cr1",
"name": "criteria1",
"measure": "Action"
},
{
"id": "cr4",
"name": "criteria4",
"measure": "Action"
}]
}
]
}]
},
{
"id": "f2",
"name": "Framework2",
"description": "framework 2 for testing",
"categories": [
{
"id": "c2",
"name": "category2",
"description": "category2",
"subCategories": [
{
"id": "sb4",
"name": "subCat5",
"description": "subCat5",
"criterias": [
{
"id": "cr1",
"name": "criteria1",
"measure": "Action"
},
{
"id": "cr3",
"name": "criteria3",
"measure": "Action"
}]
},
{
"id": "sb2",
"name": "subCat2",
"description": "subCat2",
"criterias": [
{
"id": "cr1",
"name": "criteria1",
"measure": "Action"
},
{
"id": "cr4",
"name": "criteria4",
"measure": "Action"
}]
}]
},
{
"id": "c1",
"name": "category1",
"description": "category1",
"subCategories": [
{
"id": "sb3",
"name": "subCat3",
"description": "subCat3",
"criterias": [
{
"id": "cr1",
"name": "criteria1",
"measure": "Action"
},
{
"id": "cr2",
"name": "criteria2",
"measure": "Action"
}
]},
{
"id": "sb2",
"name": "subCat2",
"description": "subCat2",
"criterias": [
{
"id": "cr1",
"name": "criteria1",
"measure": "Action"
},
{
"id": "cr4",
"name": "criteria4",
"measure": "Action"
}]
}
]
}]
}
]
Note - Category document doesn't have any reference to subcategory and same way subcategory doesn't have any reference to criteria object currently as they are master data and are generic , framework is created with their combination dynamically.
If you want to try to do all the work in the aggregation, you could group first by subcategory, then by category like:
db.collection.aggregate([
{$unwind:"$criteriaConfigs"},
{$project:{
_id:0,
category:"$criteriaConfigs.category",
subCategory:"$criteriaConfigs.subCategory",
criteria:"$criteriaConfigs.criteria"
}},
{$group:{
_id:{"category":"$category","subCategory":"$subCategory"},
criteria:{$addToSet:"$criteria"}
}},
{$group:{
_id:{"category":"$_id.category"},
subCategories:{$addToSet:{subCategory:"$_id.subCategory",
criteria:"$criteria"}}
}},
{$project:{
_id:0,category:"$_id.category",
subCategories:"$subCategories"
}}
])
Depending on how you plan to us the return data, it may be more efficient to return each unique combination:
db.collection.aggregate([
{$unwind:"$criteriaConfigs"},
{$group:{
_id:{
category:"$criteriaConfigs.category.name",
subCategory:"$criteriaConfigs.subCategory.name",
criteria:"$criteriaConfigs.criteria.name"
}
}},
{$project:{
_id:0,
category:"$_id.category",
subCategory:"$_id.subCategory",
criteria:"$_id.criteria"
}}
])
I'm not sure from your question what shape you are expecting the return data to have, so you may need to adjust for that.