206

I'm bashing my head against an error I can't work out how to fix. I have the following;

JSON

{"products":
[
    {
        "product_id" : "123",
        "product_data" : {
            "image_id" : "1234",
            "text" : "foo",
            "link" : "bar",
            "image_url" : "baz"
        }
    },{
        "product_id" : "456",
        "product_data" : {
            "image_id" : "1234",
            "text" : "foo",
            "link" : "bar",
            "image_url" : "baz"
        }
    }
]}

and the following jQuery

function getData(data) {
    this.productID = data.product_id;
    this.productData = data.product_data;
    this.imageID = data.product_data.image_id;
    this.text = data.product_data.text;
    this.link = data.product_data.link;
    this.imageUrl = data.product_data.image_url;
}

$.getJSON("json/products.json").done(function (data) {

    var allProducts = data.map(function (item) {
        return new getData(item);
    });
});

yet I'm getting an error that map.data is undefined as a function? Looking at it I don't know what's not working as I've copied this to a new project from previously used code. The only thing different is the JSON source. The previous one didn't have the {"products": part before the [] brackets. Is this what's throwing me off?

1
  • 142
    Please don't bash your head anymore - we will get through this... Commented Jun 12, 2015 at 12:51

10 Answers 10

349

Objects, {} in JavaScript do not have the method .map(). It's only for Arrays, [].

So in order for your code to work change data.map() to data.products.map() since products is an array which you can iterate upon.

Sign up to request clarification or add additional context in comments.

1 Comment

iwow it works , thanks a lot i had same issues there was a row before the data
97

The right way to iterate over objects is

Object.keys(someObject).map(function(item)...
Object.keys(someObject).forEach(function(item)...;

// ES way
Object.keys(data).map(item => {...});
Object.keys(data).forEach(item => {...});

Read here for details

2 Comments

sometimes you might be looking for values not keys > Object.values(someObject).map(function(item)... //instead of keys
sometimes you might be looking for both Key and Values => Object.entries(someObject).forEach(([key, value]) => console.log(${key}: ${value}));
27

In some cases (not in all), the SIMPLEST answer is to put "data" into a pair of square brackets (i.e. [data]) to change the items in the "data" into an array:

     $.getJSON("json/products.json").done(function (data) {

         var allProducts = [data].map(function (item) {
             return new getData(item);
         });

     });

Here, [data] is an array, and the ".map" method can be used on it. It works for me! enter image description here

Or convert "data" into an array in the following way:

     let dataArr = Array.from(data);

     $.getJSON("json/products.json").done(function (dataArr) {

         var allProducts = dataArr.map(function (item) {
             return new getData(item);
         });

     });

But the very question here is to get the "products" out of the "data":

     data.products

The "products" is an array.

And then ".map" can be used:

     data.products.map

11 Comments

Doesn't this simply create a new array with only one data element - your original object? Why do you need to map that? var data = {foo: 'bar'}; [data].map(function (item) { console.log(item); });
Yes, it DOES simply create a new array with only one data element. There is nothing wrong with that. It's not that I who need to map. It's the specific project that needs to map. If it needs to map but your data is not an array, there'll be an error. Converting it to an array just changes its format, not its values, and that's just what the project needs.
I might be missing something. It seems to me that your example would do the same thing without the map: $.getJSON("json/products.json").done(function (data) { var allProducts = new getData(data); });
@WilliamHou Let me explain the problem here with an analogy. OP has a lockbox which he needs help opening but only has a hammer that doesn't work. Instead of providing him with the key, you are suggesting he put the lockbox in a wooden box and then smash the wooden box with the hammer. Yes, he has now used the hammer but he still has the original problem -- a locked lockbox.
This is a nonsensical solution, and objectively incorrect in the context of the question. The answer is to use data.products.map, not to wrap data in an array. Your answer causes the entire data object to be passed into getData, which clearly expects one of the elements from data.products as its input, not the entire data object. Your answer will cause the program to blow up when a line like this.imageID = data.product_data.image_id; is reached. Even if this weren't the case, layering an arbitrary object in an array just so map is available is still nonsensical.
|
6

data is not an array, it is an object with an array of products so iterate over data.products

var allProducts = data.products.map(function (item) {
    return new getData(item);
});

Comments

3

If you want to map an object you can use Lodash. Just make sure it's installed via NPM or Yarn and import it.

With Lodash:

Lodash provides a function _.mapValues to map the values and preserve the keys.

_.mapValues({ one: 1, two: 2, three: 3 }, function (v) { return v * 3; });

// => { one: 3, two: 6, three: 9 }

Comments

2

data needs to be Json object, to do so please make sure the follow:

data = $.parseJSON(data);

Now you can do something like:

data.map(function (...) {
            ...
        });

I hope this help some one

Comments

0

You can always do the following:

const SomeCall = request.get(res => { 

const Store = []; 
Store.push(res.data);

Store.forEach(item => { DoSomethingNeat 
});
}); 

Comments

0
this.$http.get('https://pokeapi.co/api/v2/pokemon')
.then(response => {
   if(response.status === 200)
   {
      this.usuarios = response.data.results.map(usuario => {
      return { name: usuario.name, url: usuario.url, captched: false } })
          }
    })
.catch( error => { console.log("Error al Cargar los Datos: " + error ) } )

1 Comment

Hello Fernando, and welcome to Stack Overflow! This is an English-only site. I have edited out the part of your answer that was not posted in English. Feel free to translate it and re-add it.
0

you can use this way tooo.

// Convert Data  to array using Array.from()
    Array.from( data ).forEach(item => {
       // your logic...
    });

Comments

-1

There is an error on $.map() invocation, try this:

    function getData(data) {
        this.productID = data.product_id;
        this.productData = data.product_data;
        this.imageID = data.product_data.image_id;
        this.text = data.product_data.text;
        this.link = data.product_data.link;
        this.imageUrl = data.product_data.image_url;
    }

    $.getJSON("json.json?sdfsdfg").done(function (data) {

        var allPosts = $.map(data,function (item) {

            for (var i = 0; i < item.length; i++) {
                new getData(item[i]);
            };

        });

    }); 

The error in your code was that you made return in your AJAX call, so it executed only one time.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.