最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - JSON @attributes and @association levels with js andor angularjs - Stack Overflow

programmeradmin3浏览0评论

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.

Share Improve this question edited Jan 28, 2019 at 11:03 Ali Khaki 1,2121 gold badge15 silver badges26 bronze badges asked Dec 18, 2017 at 10:58 DeathstormDeathstorm 84712 silver badges38 bronze badges 2
  • 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
Add a comment  | 

4 Answers 4

Reset to default 8 +50

As 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:

  1. Preformatting the response object so that all the keys in JSON are JS accepted identifiers. But that would be futile work in your scenario.
  2. Second is using Object[fieldName] notation instead of Object.fieldName, because a key in the json can also be a number. Mind you an array in JS is indexed object.
发布评论

评论列表(0)

  1. 暂无评论