I'm currently working on a project that uses an API to retrieve, update and delete data. The API i'm using is the prestashop API. So after being able to retrieve data and update some items i stumbled upon an issue. As told in the documentation all data sent and retrieved through the API is with json
and xml
Since some data of the API has different levels in the json return like the @attributes and @associations levels i came up with this question.
The thing is I would like to access this data and, in combination with angularjs I would like to show this data. So let me show you a quick example of what I'm trying to achieve.
First of all the JSON
return would be something like this.
{"products":{"product":[{"id":"1","id_manufacturer":"1","id_supplier":"1","id_category_default":"5","new":{},"cache_default_attribute":"1","id_default_image":"1","id_default_combination":"1","id_tax_rules_group":"1","position_in_category":"0","manufacturer_name":"Fashion Manufacturer","quantity":"0","type":"simple","id_shop_default":"1","reference":"demo_1","supplier_reference":{},"location":{},"width":"0.000000","height":"0.000000","depth":"0.000000","weight":"0.000000","quantity_discount":"0","ean13":"333456789111","isbn":{},"upc":{},"cache_is_pack":"0","cache_has_attachments":"0","is_virtual":"0","state":"1","on_sale":"0","online_only":"0","ecotax":"0.000000","minimal_quantity":"1","price":"16.510000","wholesale_price":"4.950000","unity":{},"unit_price_ratio":"0.000000","additional_shipping_cost":"0.00","customizable":"0","text_fields":"0","uploadable_files":"0","active":"1","redirect_type":"404","id_type_redirected":"0","available_for_order":"1","available_date":"0000-00-00","show_condition":"0","condition":"new","show_price":"1","indexed":"1","visibility":"both","advanced_stock_management":"0","date_add":"2017-03-16 14:36:24","date_upd":"2017-12-01 13:01:13","pack_stock_type":"3","meta_description":{"language":{"@attributes":{"id":"1"}}},"meta_keywords":{"language":{"@attributes":{"id":"1"}}},"meta_title":{"language":{"@attributes":{"id":"1"}}},"link_rewrite":{"language":"gebleekte-T-shirts-met-korte-mouwen"},"name":{"language":"Gebleekte T-shirts met Korte Mouwen"},"description":{"language":"
Fashion maakt goed ontworpen collecties sinds 2010. Het merk biedt vrouwelijke combineerbare kleding en statement dresses en heeft een pr\u00eat-\u00e0-porter collectie ontwikkeld met kledingstukken die niet in een garderobe mogen ontbreken. Het resultaat? Cool, gemakkelijk, easy, chique met jeugdige elegantie en een duidelijk herkenbare stijl. Alle prachtige kledingstukken worden met de grootste zorg gemaakt in Itali\u00eb. Fashion breidt zijn aanbod uit met accessoires zoals schoenen, hoeden, riemen!<\/p>"},"description_short":{"language":"
Gebleekt T-shirt met korte mouwen en hoge halslijn. Zacht en elastisch materiaal zorgt voor een comfortabele pasvorm. Maak het af met een strooien hoed en u bent klaar voor de zomer!<\/p>"},"available_now":{"language":"Op voorraad"},"available_later":{"language":{"@attributes":{"id":"1"}}},"associations":{"categories":{"@attributes":{"nodeType":"category","api":"categories"},"category":[{"id":"2"},{"id":"3"},{"id":"4"},{"id":"5"}]},"images":{"@attributes":{"nodeType":"image","api":"images"},"image":[{"id":"1"},{"id":"2"},{"id":"3"},{"id":"4"}]},"combinations":{"@attributes":{"nodeType":"combination","api":"combinations"},"combination":[{"id":"1"},{"id":"2"},{"id":"3"},{"id":"4"},{"id":"5"},{"id":"6"}]},"product_option_values":{"@attributes":{"nodeType":"product_option_value","api":"product_option_values"},"product_option_value":[{"id":"1"},{"id":"13"},{"id":"14"},{"id":"2"},{"id":"3"}]},"product_features":{"@attributes":{"nodeType":"product_feature","api":"product_features"},"product_feature":[{"id":"5","id_feature_value":"5"},{"id":"6","id_feature_value":"11"},{"id":"7","id_feature_value":"17"}]},"tags":{"@attributes":{"nodeType":"tag","api":"tags"}},"stock_availables":{"@attributes":{"nodeType":"stock_available","api":"stock_availables"},"stock_available":[{"id":"1","id_product_attribute":"0"},{"id":"11","id_product_attribute":"1"},{"id":"12","id_product_attribute":"2"},{"id":"13","id_product_attribute":"3"},{"id":"22","id_product_attribute":"4"},{"id":"23","id_product_attribute":"5"},{"id":"24","id_product_attribute":"6"}]},"accessories":{"@attributes":{"nodeType":"product","api":"products"}},"product_bundle":{"@attributes":{"nodeType":"product","api":"products"}}}},
The structure simplified
products {
product {
id:
name:
category:
...
@attributes {
id:
language:
...
}
@attributes {
{"nodeType":"product_option_value","api":"product_option_values"},"product_option_value":[
{"id":"1"},
{"id":"11"},
{"id":"8"},
{"id":"2"},
{"id":"3"}
]
},
}
}
}
Using the $http.get()
function in Angularjs I'm able to retrieve the data and use an ng-repeat and bind combination to show the product_names. Now I would like to access the @attribute values and so on. But how would I be able to access them? Is there a specific way to do this? or is it purely done by accessing the depth level of the JSON object?
The AngularJS function for the products:
$http.get('config/get/getProducts.php', {cache: true}).then(function (response) {
$scope.products = response.data.products.product
});
Then in the <html>
I can simply use:
<div ng-if="product.active == 1" class="productimg col-4" ng-repeat="product in products | filter : {id_category_default: catFilter.id}: true | filter:productSearch | filter:product.name | orderBy: 'name'">
<p ng-bind="product.name.language"></p>
</div>
UPDATE: 01/02/2018 So after reading and testing some of the comments i've come up with a reasonable solution. I'm able to access the @attributes and associations values but i've stumbled upon a new problem. The return i'm getting for each filter are multiple "id" values. Take a look at the example below.
<div class="col-lg-3" ng-repeat="value in products">
<p ng-bind="value.associations.categories.category"></p>
</div>
Returns:
[{"id":"2"},{"id":"3"},{"id":"4"},{"id":"5"}]
[{"id":"2"},{"id":"3"},{"id":"4"},{"id":"5"}]
[{"id":"2"},{"id":"3"},{"id":"4"},{"id":"7"}]
Where each row of [ .. .. ] stands for a different product. Now i need to get these values as only the numbers that they are so that i can compare them with corresponsding id values from different tables. A good result would be:
2, 3, 4, 5
The question is how would i be able to get to this solution?
If anyone is interested in why and how. I'm trying to retrieve the option_values
id's and category
id's from the products from a prestashop installation, and all that through the prestashop webservice.
I'm currently working on a project that uses an API to retrieve, update and delete data. The API i'm using is the prestashop API. So after being able to retrieve data and update some items i stumbled upon an issue. As told in the documentation all data sent and retrieved through the API is with json
and xml
Since some data of the API has different levels in the json return like the @attributes and @associations levels i came up with this question.
The thing is I would like to access this data and, in combination with angularjs I would like to show this data. So let me show you a quick example of what I'm trying to achieve.
First of all the JSON
return would be something like this.
{"products":{"product":[{"id":"1","id_manufacturer":"1","id_supplier":"1","id_category_default":"5","new":{},"cache_default_attribute":"1","id_default_image":"1","id_default_combination":"1","id_tax_rules_group":"1","position_in_category":"0","manufacturer_name":"Fashion Manufacturer","quantity":"0","type":"simple","id_shop_default":"1","reference":"demo_1","supplier_reference":{},"location":{},"width":"0.000000","height":"0.000000","depth":"0.000000","weight":"0.000000","quantity_discount":"0","ean13":"333456789111","isbn":{},"upc":{},"cache_is_pack":"0","cache_has_attachments":"0","is_virtual":"0","state":"1","on_sale":"0","online_only":"0","ecotax":"0.000000","minimal_quantity":"1","price":"16.510000","wholesale_price":"4.950000","unity":{},"unit_price_ratio":"0.000000","additional_shipping_cost":"0.00","customizable":"0","text_fields":"0","uploadable_files":"0","active":"1","redirect_type":"404","id_type_redirected":"0","available_for_order":"1","available_date":"0000-00-00","show_condition":"0","condition":"new","show_price":"1","indexed":"1","visibility":"both","advanced_stock_management":"0","date_add":"2017-03-16 14:36:24","date_upd":"2017-12-01 13:01:13","pack_stock_type":"3","meta_description":{"language":{"@attributes":{"id":"1"}}},"meta_keywords":{"language":{"@attributes":{"id":"1"}}},"meta_title":{"language":{"@attributes":{"id":"1"}}},"link_rewrite":{"language":"gebleekte-T-shirts-met-korte-mouwen"},"name":{"language":"Gebleekte T-shirts met Korte Mouwen"},"description":{"language":"
Fashion maakt goed ontworpen collecties sinds 2010. Het merk biedt vrouwelijke combineerbare kleding en statement dresses en heeft een pr\u00eat-\u00e0-porter collectie ontwikkeld met kledingstukken die niet in een garderobe mogen ontbreken. Het resultaat? Cool, gemakkelijk, easy, chique met jeugdige elegantie en een duidelijk herkenbare stijl. Alle prachtige kledingstukken worden met de grootste zorg gemaakt in Itali\u00eb. Fashion breidt zijn aanbod uit met accessoires zoals schoenen, hoeden, riemen!<\/p>"},"description_short":{"language":"
Gebleekt T-shirt met korte mouwen en hoge halslijn. Zacht en elastisch materiaal zorgt voor een comfortabele pasvorm. Maak het af met een strooien hoed en u bent klaar voor de zomer!<\/p>"},"available_now":{"language":"Op voorraad"},"available_later":{"language":{"@attributes":{"id":"1"}}},"associations":{"categories":{"@attributes":{"nodeType":"category","api":"categories"},"category":[{"id":"2"},{"id":"3"},{"id":"4"},{"id":"5"}]},"images":{"@attributes":{"nodeType":"image","api":"images"},"image":[{"id":"1"},{"id":"2"},{"id":"3"},{"id":"4"}]},"combinations":{"@attributes":{"nodeType":"combination","api":"combinations"},"combination":[{"id":"1"},{"id":"2"},{"id":"3"},{"id":"4"},{"id":"5"},{"id":"6"}]},"product_option_values":{"@attributes":{"nodeType":"product_option_value","api":"product_option_values"},"product_option_value":[{"id":"1"},{"id":"13"},{"id":"14"},{"id":"2"},{"id":"3"}]},"product_features":{"@attributes":{"nodeType":"product_feature","api":"product_features"},"product_feature":[{"id":"5","id_feature_value":"5"},{"id":"6","id_feature_value":"11"},{"id":"7","id_feature_value":"17"}]},"tags":{"@attributes":{"nodeType":"tag","api":"tags"}},"stock_availables":{"@attributes":{"nodeType":"stock_available","api":"stock_availables"},"stock_available":[{"id":"1","id_product_attribute":"0"},{"id":"11","id_product_attribute":"1"},{"id":"12","id_product_attribute":"2"},{"id":"13","id_product_attribute":"3"},{"id":"22","id_product_attribute":"4"},{"id":"23","id_product_attribute":"5"},{"id":"24","id_product_attribute":"6"}]},"accessories":{"@attributes":{"nodeType":"product","api":"products"}},"product_bundle":{"@attributes":{"nodeType":"product","api":"products"}}}},
The structure simplified
products {
product {
id:
name:
category:
...
@attributes {
id:
language:
...
}
@attributes {
{"nodeType":"product_option_value","api":"product_option_values"},"product_option_value":[
{"id":"1"},
{"id":"11"},
{"id":"8"},
{"id":"2"},
{"id":"3"}
]
},
}
}
}
Using the $http.get()
function in Angularjs I'm able to retrieve the data and use an ng-repeat and bind combination to show the product_names. Now I would like to access the @attribute values and so on. But how would I be able to access them? Is there a specific way to do this? or is it purely done by accessing the depth level of the JSON object?
The AngularJS function for the products:
$http.get('config/get/getProducts.php', {cache: true}).then(function (response) {
$scope.products = response.data.products.product
});
Then in the <html>
I can simply use:
<div ng-if="product.active == 1" class="productimg col-4" ng-repeat="product in products | filter : {id_category_default: catFilter.id}: true | filter:productSearch | filter:product.name | orderBy: 'name'">
<p ng-bind="product.name.language"></p>
</div>
UPDATE: 01/02/2018 So after reading and testing some of the comments i've come up with a reasonable solution. I'm able to access the @attributes and associations values but i've stumbled upon a new problem. The return i'm getting for each filter are multiple "id" values. Take a look at the example below.
<div class="col-lg-3" ng-repeat="value in products">
<p ng-bind="value.associations.categories.category"></p>
</div>
Returns:
[{"id":"2"},{"id":"3"},{"id":"4"},{"id":"5"}]
[{"id":"2"},{"id":"3"},{"id":"4"},{"id":"5"}]
[{"id":"2"},{"id":"3"},{"id":"4"},{"id":"7"}]
Where each row of [ .. .. ] stands for a different product. Now i need to get these values as only the numbers that they are so that i can compare them with corresponsding id values from different tables. A good result would be:
2, 3, 4, 5
The question is how would i be able to get to this solution?
If anyone is interested in why and how. I'm trying to retrieve the option_values
id's and category
id's from the products from a prestashop installation, and all that through the prestashop webservice.
- I don't see any other option here. You will have to access by depth level. If you know the JSON structure, you can parse and convert into more convenient structure. That way you will have to do it only once and can be accessed everywhere. – Ashish Commented Dec 21, 2017 at 10:47
- @Ashish What do you think i've been trying to do? – Deathstorm Commented Dec 21, 2017 at 10:48
4 Answers
Reset to default 8 +50As I understand you would like to use ng-repeat with nested JSON objects. You will need to use more than one repeater because a single repeated item can contain multiple items of its own which you would like to display.
So as far as I can see something like this should work:
<div ng-if="product.active == 1" class="productimg col-4" ng-repeat="product in products | filter : {id_category_default: catFilter.id}: true | filter:productSearch | filter:product.name | orderBy: 'name'">
<p ng-bind="product.name.language"></p>
<table ng-repeat="cat in product.associations.categories">
<tr ng-repeat="attr in cat.@attributes">
<td >{{attr.nodeType}}</td>
<td >{{attr.api}}</td>
</tr>
</table>
</div>
Have a look here: https://www.aspsnippets.com/Articles/AngularJS-Using-ng-repeat-with-Complex-Nested-JSON-objects.aspx
I think your only issue is accessing the @attributes with the dot notation like so product.associations.categories.@attributes
this is not valid javascript, so instead you should use the bracket notation for this attributes.
like so: product.associations.categories['@attributes']
From your question I understand that the problem is accessing the @attribute
properties inside ng-repeat
, please find below an example showing the @attribute
values using ng-repeat
we can also access object properties using bracket notation
instead of dot notation
, read more here.
Please let me know if this answer has helped solve your issue, or if I have missed something in my answer.
var app = angular.module('myapp', []);
app.controller('MainCtrl', function($scope) {
$scope.products = [{
"id": "1",
"id_manufacturer": "1",
"id_supplier": "1",
"id_category_default": "5",
"new": {
},
"cache_default_attribute": "1",
"id_default_image": "1",
"id_default_combination": "1",
"id_tax_rules_group": "1",
"position_in_category": "0",
"manufacturer_name": "Fashion Manufacturer",
"quantity": "0",
"type": "simple",
"id_shop_default": "1",
"reference": "demo_1",
"supplier_reference": {
},
"location": {
},
"width": "0.000000",
"height": "0.000000",
"depth": "0.000000",
"weight": "0.000000",
"quantity_discount": "0",
"ean13": "333456789111",
"isbn": {
},
"upc": {
},
"cache_is_pack": "0",
"cache_has_attachments": "0",
"is_virtual": "0",
"state": "1",
"on_sale": "0",
"online_only": "0",
"ecotax": "0.000000",
"minimal_quantity": "1",
"price": "16.510000",
"wholesale_price": "4.950000",
"unity": {
},
"unit_price_ratio": "0.000000",
"additional_shipping_cost": "0.00",
"customizable": "0",
"text_fields": "0",
"uploadable_files": "0",
"active": "1",
"redirect_type": "404",
"id_type_redirected": "0",
"available_for_order": "1",
"available_date": "0000-00-00",
"show_condition": "0",
"condition": "new",
"show_price": "1",
"indexed": "1",
"visibility": "both",
"advanced_stock_management": "0",
"date_add": "2017-03-16 14:36:24",
"date_upd": "2017-12-01 13:01:13",
"pack_stock_type": "3",
"meta_description": {
"language": {
"@attributes": {
"id": "1"
}
}
},
"meta_keywords": {
"language": {
"@attributes": {
"id": "1"
}
}
},
"meta_title": {
"language": {
"@attributes": {
"id": "1"
}
}
},
"link_rewrite": {
"language": "gebleekte-T-shirts-met-korte-mouwen"
},
"name": {
"language": "Gebleekte T-shirts met Korte Mouwen"
},
"description": {
"language": "Fashion maakt goed ontworpen collecties sinds 2010. Het merk biedt vrouwelijke combineerbare kleding en statement dresses en heeft een pr\u00eat-\u00e0-porter collectie ontwikkeld met kledingstukken die niet in een garderobe mogen ontbreken. Het resultaat? Cool, gemakkelijk, easy, chique met jeugdige elegantie en een duidelijk herkenbare stijl. Alle prachtige kledingstukken worden met de grootste zorg gemaakt in Itali\u00eb. Fashion breidt zijn aanbod uit met accessoires zoals schoenen, hoeden, riemen!<\/p>"
},
"description_short": {
"language": "Gebleekt T-shirt met korte mouwen en hoge halslijn. Zacht en elastisch materiaal zorgt voor een comfortabele pasvorm. Maak het af met een strooien hoed en u bent klaar voor de zomer!<\/p>"
},
"available_now": {
"language": "Op voorraad"
},
"available_later": {
"language": {
"@attributes": {
"id": "1"
}
}
},
"associations": {
"categories": {
"@attributes": {
"nodeType": "category",
"api": "categories"
},
"category": [{
"id": "2"
},
{
"id": "3"
},
{
"id": "4"
},
{
"id": "5"
}
]
},
"images": {
"@attributes": {
"nodeType": "image",
"api": "images"
},
"image": [{
"id": "1"
},
{
"id": "2"
},
{
"id": "3"
},
{
"id": "4"
}
]
},
"combinations": {
"@attributes": {
"nodeType": "combination",
"api": "combinations"
},
"combination": [{
"id": "1"
},
{
"id": "2"
},
{
"id": "3"
},
{
"id": "4"
},
{
"id": "5"
},
{
"id": "6"
}
]
},
"product_option_values": {
"@attributes": {
"nodeType": "product_option_value",
"api": "product_option_values"
},
"product_option_value": [{
"id": "1"
},
{
"id": "13"
},
{
"id": "14"
},
{
"id": "2"
},
{
"id": "3"
}
]
},
"product_features": {
"@attributes": {
"nodeType": "product_feature",
"api": "product_features"
},
"product_feature": [{
"id": "5",
"id_feature_value": "5"
},
{
"id": "6",
"id_feature_value": "11"
},
{
"id": "7",
"id_feature_value": "17"
}
]
},
"tags": {
"@attributes": {
"nodeType": "tag",
"api": "tags"
}
},
"stock_availables": {
"@attributes": {
"nodeType": "stock_available",
"api": "stock_availables"
},
"stock_available": [{
"id": "1",
"id_product_attribute": "0"
},
{
"id": "11",
"id_product_attribute": "1"
},
{
"id": "12",
"id_product_attribute": "2"
},
{
"id": "13",
"id_product_attribute": "3"
},
{
"id": "22",
"id_product_attribute": "4"
},
{
"id": "23",
"id_product_attribute": "5"
},
{
"id": "24",
"id_product_attribute": "6"
}
]
},
"accessories": {
"@attributes": {
"nodeType": "product",
"api": "products"
}
},
"product_bundle": {
"@attributes": {
"nodeType": "product",
"api": "products"
}
}
}
}];
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-controller="MainCtrl" ng-app="myapp">
<div ng-if="product.active == 1" class="productimg col-4" ng-repeat="product in products | filter : {id_category_default: catFilter.id}: true | filter:productSearch | filter:product.name | orderBy: 'name'">
<p ng-bind="product.name.language"></p>
<div ng-repeat="(key,value) in product['meta_title']['language']['@attributes']">
Key: {{key}} , Value: {{value}}
</div>
</div>
</div>
You have clearly two options for solving this problems of yours:
- Preformatting the response object so that all the keys in JSON are JS accepted identifiers. But that would be futile work in your scenario.
- Second is using
Object[fieldName]
notation instead ofObject.fieldName
, because a key in the json can also be a number. Mind you an array in JS is indexed object.