javascript - unescape - recorrer json angularjs
JSON @attributes y @asociaciones con js y/o angularjs (4)
Actualmente estoy trabajando en un proyecto que utiliza una API para recuperar, actualizar y eliminar datos. La API que estoy usando es la API de prestashop . Así que después de poder recuperar datos y actualizar algunos elementos, me topé con un problema. Como se indica en la documentación, todos los datos enviados y recuperados a través de la API son con json
y xml
Dado que algunos datos de la API tienen diferentes niveles en el retorno de json como los atributos de @attributes y @associations, se me ocurrió esta pregunta.
La cosa es que me gustaría acceder a estos datos y, en combinación con angularjs me gustaría mostrar estos datos. Así que déjame mostrarte un ejemplo rápido de lo que estoy tratando de lograr.
En primer lugar, el retorno de JSON
sería algo como esto.
{"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"}}}},
La estructura simplificada.
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"}
]
},
}
}
}
Al usar la función $http.get()
en Angularjs, puedo recuperar los datos y usar una combinación ng-repeat y bind para mostrar los nombres de producto. Ahora me gustaría acceder a los valores de @attribute y así sucesivamente. ¿Pero cómo podría acceder a ellos? ¿Hay una manera específica de hacer esto? ¿O se hace puramente accediendo al nivel de profundidad del objeto JSON?
La función AngularJS para los productos:
$http.get(''config/get/getProducts.php'', {cache: true}).then(function (response) {
$scope.products = response.data.products.product
});
Luego en el <html>
simplemente puedo usar:
<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>
ACTUALIZACIÓN: 01/02/2018 Entonces, después de leer y probar algunos de los comentarios, he encontrado una solución razonable. Soy capaz de acceder a los valores de @atributos y asociaciones, pero me he topado con un nuevo problema. El retorno que estoy obteniendo para cada filtro son múltiples valores de "id". Echa un vistazo al siguiente ejemplo.
<div class="col-lg-3" ng-repeat="value in products">
<p ng-bind="value.associations.categories.category"></p>
</div>
Devoluciones:
[{"id":"2"},{"id":"3"},{"id":"4"},{"id":"5"}]
[{"id":"2"},{"id":"3"},{"id":"4"},{"id":"5"}]
[{"id":"2"},{"id":"3"},{"id":"4"},{"id":"7"}]
Donde cada fila de [.. ..] representa un producto diferente. Ahora necesito obtener estos valores como solo los números que son para poder compararlos con los valores de identificación correspondientes de diferentes tablas. Un buen resultado sería:
2, 3, 4, 5
La pregunta es, ¿cómo podría llegar a esta solución?
Si alguien está interesado en por qué y cómo. Estoy tratando de recuperar los id. De option_values
identificadores de category
de los productos de una instalación prestashop, y todo eso a través del servicio web prestashop.
Creo que su único problema es acceder a los atributos @ con la notación de puntos como product.associations.categories.@attributes
esto no es un javascript válido, por lo que debería usar la notación de corchete para estos atributos.
así: product.associations.categories[''@attributes'']
De su pregunta, entiendo que el problema es acceder a las propiedades de @attribute
dentro de ng-repeat
, a continuación encontrará un ejemplo que muestra los valores de @attribute
usando ng-repeat
. También podemos acceder a las propiedades de objetos usando la bracket notation
lugar de dot notation
de dot notation
, lea más here .
Por favor, avíseme si esta respuesta ha ayudado a resolver su problema o si me he perdido algo en mi respuesta.
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>
Según tengo entendido, le gustaría usar ng-repeat con objetos JSON anidados. Deberá usar más de un repetidor porque un solo elemento repetido puede contener varios elementos propios que le gustaría mostrar.
Por lo que puedo ver algo como esto debería funcionar:
<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>
Eche un vistazo aquí: https://www.aspsnippets.com/Articles/AngularJS-Using-ng-repeat-with-Complex-Nested-JSON-objects.aspx
Tienes claramente dos opciones para resolver estos problemas tuyos:
- Preformatear el objeto de respuesta para que todas las claves en JSON sean identificadores aceptados por JS. Pero eso sería un trabajo inútil en su escenario.
- El segundo es usar la notación
Object[fieldName]
lugar deObject.fieldName
, porque una clave en el json también puede ser un número. Tenga en cuenta que una matriz en JS es objeto indexado.