0

I have a api (in NODEJS) response that gives back an array:

res.json(friends)
[
    {
        "id": 7795239,
        "username": "janesmith"
    },
    {
        "id": 1363327,
        "username": "johnsmith"
    }
]

But when I want to iterate through the array before sending this response, I cannot find the way to do this. users.length does not exist, for(var key users) doens't work either.

How to solve this?

edit: the code where it gets the array:

User.find({}, function(err, users){
    if(err) res.send(err);
    var friends;
    var result = 'this will hold the result';

    for(var key in users){
        if(users[key].username == req.decoded.username) {
            friends = users[key].friends;
        }
    }

    // here I want to do things with the list of friends, so this is the place where I need to iterate over it

    res.json(result);
});

This is the log result for users and err

users: 
    [
        {
            "_id": "5710b02c7787794009325f62",
            "username": "demouser",
            "__v": 0,
            "friends": 
            [
                {
                    "username": "janesmith",
                    "id": 7795239
                },
                {
                    "username": "johnsmith",
                    "id": 1363327
                }
            ]
        }
    ]   
err: null

This is the log of the keys:

toObject
toJSON
items
db
discriminators
__v
id
_id
friends
password
username
userID
schema
collection
comparePassword
save
$__delta
$__version
increment
$__where
remove
model
$__buildDoc
init
$__storeShard
hook
pre
post
removePre
_lazySetupHooks
update
set
$__shouldModify
$__set
getValue
setValue
get
$__path
markModified
$__try
modifiedPaths
isModified
isDirectModified
isInit
isSelected
validate
invalidate
$__reset
$__dirty
$__setSchema
$__registerHooks
$__error
$__doQueue
$toObject
inspect
toString
equals
populate
populated
$__fullPath
domain
_events
_maxListeners
setMaxListeners
getMaxListeners
emit
addListener
on
once
removeListener
removeAllListeners
listeners
listenerCount
stijnpiron
  • 359
  • 2
  • 4
  • 15
  • 1
    Can you post a demo to reproduce the issue? – elclanrs Apr 15 '16 at 15:05
  • 1
    Need to see more code to answer. Can you show where you're assigning the array? – spongessuck Apr 15 '16 at 15:05
  • If you parse that JSON (without the res.json(users), of course) into an object, then you should be able to iterate over its properties without issue. – ManoDestra Apr 15 '16 at 15:06
  • 1
    If `users.length` doesn't exist, it's neither an array nor a string. What do you get when you log/inspect `users`? – spongessuck Apr 15 '16 at 15:14
  • 1
    what's the result of the `console.log(err);` and `console.log(users);`? – Hugo S. Mendes Apr 15 '16 at 15:15
  • Try to add your function to a var like: var obj = res.json(users) then try to loop the obj for(x in obj){ alert(obj[x].id) } – Jorge Mejia Apr 15 '16 at 15:31
  • I didn't receive any error here: https://jsfiddle.net/qbm6g3Lv/3/ – Hugo S. Mendes Apr 15 '16 at 15:32
  • @HugoS.Mendes I can log to the console, no problem, but I cannot iterate through the friends... – stijnpiron Apr 15 '16 at 15:36
  • @stijnpiron check this out https://jsfiddle.net/qbm6g3Lv/4/ – Hugo S. Mendes Apr 15 '16 at 15:37
  • If `users.length` doesn't exist then it's not an array, or maybe some other bit of code is changing the Array prototype. What other libraries are you using? – spongessuck Apr 15 '16 at 15:38
  • @spongessuck at that point, I am not using any special libraries... Just a call to my mongo database through monoose in nodejs @HugoS.Mendes If I do that, I got an `TypeError: Cannot read property 'username' of undefined` – stijnpiron Apr 15 '16 at 15:41
  • that's really odd.. because it's working in the fiddle. – Hugo S. Mendes Apr 15 '16 at 15:42
  • @HugoS.Mendes Agreed, that's why I feel like something else is going on. @stijnpiron, what do you get when you log out all of the `key`s? – spongessuck Apr 15 '16 at 15:43
  • Seems like `users` is somehow getting the one user you have in the array. Try commenting out your loop and doing this instead: `if(users.username == req.decoded.username) { friends = users.friends; }` – spongessuck Apr 15 '16 at 15:55
  • To clarify: There is more than 1 user, I only want the set of friends of the user that is selected. So shouldn't that be like I did then? – stijnpiron Apr 15 '16 at 15:58
  • It should, but `users` is clearly not an array, and it has `_id`, `username`, and `friends` properties like your individual users should. – spongessuck Apr 15 '16 at 15:59
  • wait.. what does it show? console.log(req.decoded.username) ? – Hugo S. Mendes Apr 15 '16 at 16:05
  • could you try to iterate friends like this: `console.log(friends.map(a => a.username));` ? – Hugo S. Mendes Apr 15 '16 at 16:09
  • @HugoS.Mendes - `console.log(req.decoded.username) = demouser`, trying to iterate like you suggested: `TypeError: friends.map is not a function` – stijnpiron Apr 15 '16 at 16:12
  • okay.. then can you change the name of the variable and declare it like this: `var ftest = {};`? just for test effect. – Hugo S. Mendes Apr 15 '16 at 16:15
  • same story I'm afraid `TypeError: ftest.map is not a function` – stijnpiron Apr 15 '16 at 16:18
  • That's because `map` is not a method for Object types. Did you try what I suggested? – spongessuck Apr 15 '16 at 16:20
  • wth.. how's that possible.. you told us that if you console.log(friends) it would show you the values, right? can you show us the `console.log(friends)` result? – Hugo S. Mendes Apr 15 '16 at 16:20
  • @HugoS.Mendes - This is the console.log for friends: `[ { id: 7795239, username: 'janesmith' }, { id: 1363327, username: 'johnsmith' }]` - @spongessuck Yes, after that loop, friends is undefined – stijnpiron Apr 15 '16 at 16:25
  • I told you to not use the loop. It's not finding your user because the keys aren't indeces in an array, they're the properties of the object, because, as I said, `users` is a single object and not an array. – spongessuck Apr 15 '16 at 16:27

3 Answers3

0

Simply initialize your results variable as an array and push the users you wish to match into that array and return it.

User.find({}, function(err, users){
    if (err) res.send(err);

    var result = [];
    for (var key in users) {
        if (users[key].username == req.decoded.username) {
            var friends = users[key].friends;
            for (var i = 0; i < friends.length; i++) {
                // Do stuff with each friend here, as required.
            }

            result.push(users[key]);

            // OR this, depending on whether it is users or friends you're trying to return.
            result.push(friends[i]);
        }
    }

    res.json(result);
});
ManoDestra
  • 6,325
  • 6
  • 26
  • 50
  • This should be a comment, not an answer. – trincot Apr 15 '16 at 15:15
  • No, it's an answer to his issue. He simply needs to parse the JSON into an object and he's done. And this answer illustrates how to do it, using the very JSON string he's given. I have illustrated that after parsing the JSON correctly, it's perfectly possible to access the length property of the array and then access properties from the objects in that array. – ManoDestra Apr 15 '16 at 15:16
  • I got an error when I try to parse this: `undefined:1 [ { id: 7795239, username: 'janesmith' }, ^ SyntaxError: Unexpected token i at Object.parse (native)` – stijnpiron Apr 15 '16 at 15:18
  • Like I said, this is not an answer.... @stijnpiron, there are some open questions in comments which need an answer first. – trincot Apr 15 '16 at 15:20
  • Even though it entirely answers his question? Interesting. – ManoDestra Apr 15 '16 at 15:28
  • @stijnpiron Are you parsing the JSON precisely as I've specified above, without the res.json(friends) part? It works perfectly without that. If you have a separate issue, then I suggest you raise a fresh question for your new issue. – ManoDestra Apr 15 '16 at 15:30
  • But I want to parse the result as JSON to get a JSON response, it is now sending `friends` so it sends something, but first I need to do all kind of things with the friends, like counting and comparing, let me adjust my original post to be clear... – stijnpiron Apr 15 '16 at 15:33
  • Simply parse the users JSON string that comes back using JSON.parse(jsonString) and you'll have the array of friends to iterate over or do what you wish with it. I just tried it given your new JSON string and it works fine. You need to ensure that you're not trying to parse that `res.json(friends)` part though. It won't parse if that's part of your JSON string. And from your question text, it appears to be. Just remove that and parse the actual JSON string and you're good. – ManoDestra Apr 15 '16 at 15:41
  • I've amended my answer given your edited question and extended JSON string, showing that the new JSON string parses fine into an object, without `res.json(friends)`. And you can then iterate over its properties and do whatever you wish with it. If you're issue is that you're returning friends rather than users, then just return the users rather than friends, if you still require properties from the friends parent user, of course. But provided you return the appropriate JSON, then it parses fine. – ManoDestra Apr 15 '16 at 15:48
  • when I copy the repsonse and use that as the input, it works indeed. But how does this solve my problem? As I cannot do that every time there is an API request... – stijnpiron Apr 15 '16 at 15:54
  • If the API is returning res.json(friends) at the top, then either the API needs to be fixed to return JSON only so that you can parse it without issue. Or you need to amend it after getting the response and parse accordingly. That's the only options here. The JSON part of the response is absolutely fine and parses without issue, allowing you to do exactly what you require. So, fix the API (best option) or amend the response and parse (next best). – ManoDestra Apr 15 '16 at 16:04
  • But the parsing is not an issue. The issue happens before the parsing and sending the response, so indeed the response is totally fine, because that has never been a part of my problem... And fixing the API... That is exactly what I am trying to do here... – stijnpiron Apr 15 '16 at 16:20
  • So, just stringify the object you wish to return and then send it back via your API. Which will allow you to parse it on receipt. Your users are already an array, as are the friends child node. So, there should be no issue here. If you don't think this answers your query, then I'll just remove the answer as I'm failing to see what's difficult about sending back basic JSON via an API and then parsing it on receipt. You have the right structure, so just return it as a JSON string and parse it accordingly. – ManoDestra Apr 15 '16 at 16:35
  • returning JSON is not the issue, the failure to work with with the data before it is returned is the issue. – stijnpiron Apr 15 '16 at 16:37
  • Are you trying to return an array of users? If you are, then why not simply initialize your result variable as an array and then just push the users with matching usernames to that array and return it? I'll change my answer to reflect this, given this new information. – ManoDestra Apr 15 '16 at 16:39
  • Answer updated. Let me know whether it is users or friends you're returning and what you're going to do with friends and I'll refine my answer accordingly. – ManoDestra Apr 15 '16 at 16:46
0

Seems like the find method of your API is returning an object instead of an array.

User.find({}, function(err, users){

    /* You expect users to be an array, but I suspect this is actually what it is:

    users = {
        "_id": "5710b02c7787794009325f62",
        "username": "demouser",
        "__v": 0,
        "friends": 
        [
            {
                "username": "janesmith",
                "id": 7795239
            },
            {
                "username": "johnsmith",
                "id": 1363327
            }
        ]
    }
    */

    if(err) res.send(err);
    var friends;
    var result = 'this will hold the result';

    /* Try without the loop to confirm:
    for(var key in users){
        if(users[key].username == req.decoded.username) {
            friends = users[key].friends;
        }
    }*/

    if(users.username == req.decoded.username) {
        friends = users.friends;
    }

    // here I want to do things with the list of friends, so this is the place where I need to iterate over it

    res.json(result);
});
spongessuck
  • 1,023
  • 8
  • 23
  • Tried this, but got `[]` in the console afterwards – stijnpiron Apr 15 '16 at 16:52
  • Well, obviously `users` has a property called `friends` which is an empty array, which is not what you were expecting, but it does have `username` matching `req.decoded.username` or `friends` would be `undefined`. I'm still convinced this API isn't returning back what you want and that what you posted as the value of `users` is not what it actually is. – spongessuck Apr 15 '16 at 17:15
0
var array1 = ['a', 'b', 'c'];

array1.forEach(function(element) {
  console.log(element);
});

// expected output: "a"
// expected output: "b"
// expected output: "c"
Fares Younis
  • 59
  • 1
  • 6