What is the format of Express' req.params? - javascript

I've got a weird thing I'm running into with req.params while working with Express. It works fine for calling the subordinate properties - e.g.: res.json(req.params.paramName); gives me the desired paramName value. But when I tried to pass the entire res.params object to the client via res.json(req.params), I just get an empty array [] in the browser instead of the JSON object I was expecting. (res.send gives the same result.)
Looking a bit deeper, I dumped req.params to the console:
console.dir(req.params);
and got this:
[ creator: '1', timeStart: '2', timeEnd: '3', dateDensity: '4' ]
wut? Is that even syntactically possible in Javascript?
If req.params is a simple object like the Express code and documentation indicate, I should be getting:
{ creator: '1', timeStart: '2', timeEnd: '3', dateDensity: '4' }
An array like what I'm getting above should even be possible, should it?
I did some sanity checks and passed a couple of test objects to the console as well:
console.dir([{foo:1}, {arr:2}, {gog:3}, {blah:4}]);
console.dir({foo:1, arr:2, gog:3, blah:4});
and the console dump gives me:
[ { foo: 1 }, { arr: 2 }, { gog: 3 }, { blah: 4 } ]
{ foo: 1, arr: 2, gog: 3, blah: 4 }
So console.dir is working OK.
Lastly, I hardcoded a:
res.json({foo:1, arr:2, gog:3, blah:4});
into my Express code and the browser dutifully gives me:
{
"foo": 1,
"arr": 2,
"gog": 3,
"blah": 4
}
Am I smoking crack here? What is going on with req.params?

That's how v8 prints out arrays with string keys:
var myArr = [];
myArr.key = "oops";
Remember, [] instanceof Object is true.
req.params is an array, suggesting the possibility of positional params.

Related

What's the benefit of using an array of key: value pairs over a single object?

In a few different places I've seen the following being used:
const arr = [
{ key: "someKey", value: 1 },
{ key: "anotherKey", value: true },
{ key: "yetAnotherOne", value: "hello world" },
];
To me, it seems more logical to use this structure:
const ob = {
someKey: 1,
anotherKey: true,
yetAnotherOne: "hello world",
};
Is there an advantage when using an array like this?
Arrays are explicitly ordered.
An array is typically used for a list of similar objects. Some advantages would be:
having a selection of array-specific methods to e.g. to filter/sort the objects
In an array of objects it would be possible to use the same key-property multiple times. In an object these would be overwritten.
That's all I could think of. Hope it's helpful ;).
That said I would normally recommend using an object if the above is not relevant.
In your example, it would be better to use the object because it means you can access the value of the property faster and easier using something like ob.anotherKey without having to use a loop or having to know the index in the array.
However, this might not always be the case...
Slightly different from the example above:
const people = [
{ firstName: "someKey", lastName: 1 },
{ firstName: "anotherKey", lastName: true },
{ firstName: "yetAnotherOne", lastName: "hello world" },
];
Is much easier to understand and a better representation of the data and than...
const people = {
someKey: 1,
anotherKey: true,
yetAnotherOne: "hello world",
};
This also requires previous knowledge that each key is the firstName and each value is the lastName.

Javascript Joi Alternatives Array or Array of Objects

I'm confused about Joi alternatives. I can't figure out how the alternatives are invoked against the item to tb validated.
function validateCourse(course) {
const objectSchema = {
id: Joi.number().required(),
name: Joi.string().min(3).required()
};
const arraySchema = Joi.array().items(Joi.object(objectSchema)).required();
return Joi.alternatives(objectSchema, arraySchema).validate(course);
}
This works for the object but not for the array of objects.
[
{
"id": 10,
"name": "XY"
},
{
"id": 11,
"name": "JFK"
}
]
I'm not sure if my array schema is at fault or my use of alternatives?
It appears it is working! However the invalidation message returned by the Joi when validating an array is vague when compared to validating the object.
validating object : "name" length must be at least 3 characters long
validating array : "value" must be an object
Which is not completely useful as now I have to potentially check hundreds of items to find the one at fault.
But that's a different issue consider this closed!
There is nothing wrong with your schema. The error you are getting with the array is:
"value" must be an object, "value" at position 0 fails because
[child "name" fails because ["name" length must be at least 3 characters long]]
Which is right, your name key must have at least 3 characters.
And, as you asked, you can get the object(s) that failed from the error description or
you can also use any.error(err) in order to keep track of those objects.
For instance, if you want to know the array indexes that failed you can do:
const arraySchema = Joi.array().items(Joi.object(objectSchema)).required().error((errors) => {
const indexes = errors.map((err) => err.path[0]);
return new Error(`Indexes with error: ${indexes}`)
})
For this array of objects:
[
{
'id': 11,
'name': 'ABC'
},
{
'id': 22,
'name': 'ABC'
},
{
'id': 33,
'name': 'XY'
},
{
'id': 44,
'name': 'ABC'
},
{
'id': 55,
'name': 'XY'
},
]
The error will be:
Indexes with error: 2,4
You can access your error message by doing:
validationResult.error.message
Don't forget to use { abortEarly: false } in your validation:
Joi.alternatives(objectSchema, arraySchema).validate(course, { abortEarly: false })
Worked as described for arrays but then displayed nothing for non arrays so I made a small change :
const arraySchema =
Joi.array().items(Joi.object(objectSchema)).required().error((errors) =>
{
if (errors[0].path.length)
{
const indexes = errors.map((err) => err.path[0]);
if (indexes.length) return new Error(`Indexes with error: ${indexes}`);
}
return errors;
});
So if it's an array I return the array of bad indexes (as you suggested). But if it's an object I just return { errors } unchanged.

Loop through an array of objects and get where object.field equals value

I'm currently working on a small application where I have to loop through an enormous array of objects. What would be the most efficient method to perform this?
var array = [
{
id: "1",
name: "Alpha"
},
{
id: "2",
name: "Beta"
},
...
];
I'd like to get each object where name equals "Alpha". I'm currently using a simple if statement to filter the objects with a different name value out, but I wonder if there's a more efficient way to do this, performance-wise.
It's worth to mention that I'll push the matching results into a new array.
No, there is no more efficient way.
The alternative is to build and maintain some kind of internal data structure which allows you to find the desired elements faster. As usual, the trade off is between the work involved in maintaining such a structure vs the time it saves you.
I don't have any way about which I would know it's more effective.
But if you had your objects ordered by name you could stop your search imideatly upon reaching an object whose name is not equal to "Alpha".
To find the first object you're looking for you can use binary search and from this Object you go up and down until at both ends you reach an object which isn't named "Alpha" or the end of array.
This is only a way of optimizing and will require time to sort the array and also will take more time when adding an element.
There's a JavaScript function exactly for this kind of task. Filter
From the Docs
The filter() method creates a new array with all elements that pass the test implemented by the provided function.
Here is a small example by code for getting all element from array which has a certain 'name' field:
const arr = [
{name: 'Abc'},
{name: 'Xyz'},
{name: 'Lmn'},
{name: 'Xyz'},
{name: 'Xyz'}
];
let response = findByName('Xyz');
console.log(response);
function findByName (name) {
return arr.filter((element) => {
return element.name = name;
});
}
If you need more than one time a collection with a given name, you could use an object with the names as hashes and have instantly access to the items.
var array = [{ id: "1", name: "Alpha" }, { id: "2", name: "Beta" }, { id: "3", name: "Beta" }, { id: "4", name: "Gamma" }, { id: "5", name: "Beta" }, { id: "2", name: "Alpha" }],
hash = Object.create(null);
array.forEach(function (a) {
if (!hash[a.name]) {
hash[a.name] = [];
}
hash[a.name].push(a);
});
console.log(hash);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Accessing specific values in JSON object

I can't figure out what I'm doing wrong when accessing this JSON object:
{ Items:
[ { mId: 'who' },
{ mId: 'am' },
{ mId: 'I' } ],
Count: 3,
ScannedCount: 3 }
{ Items:
[ { cId: 'big' },
{ cId: 'scary' },
{ cId: 'muppet' } ],
Count: 3,
ScannedCount: 3 }
This is the object I am getting back from a function and I'm trying to access the individual items to update their values.
When I want to print 'who' for example, I do this:
console.log(obj.Items[0].mId)
Now I expect to get 'who' back, but this is what prints:
undefined
who
That 'undefined' always tags along. What am I doing wrong here?
Also, if I try to change the value somewhere by doing:
obj.Items[0].mId = 'x'
This happens:
{ Items:
[ { mId: 'x' },
{ mId: 'am' },
{ mId: 'I' } ],
Count: 3,
ScannedCount: 3 }
{ Items:
[ { cId: 'big', mId: 'x' },
{ cId: 'scary' },
{ cId: 'muppet' } ],
Count: 3,
ScannedCount: 3 }
This is not what I want.. I don't understand how to access only the first 'Items'. It seems like I'm accessing both.
Any help or advice is greatly appreciated. I probably don't need to say that I'm not very used to working with JSON.
For the undefined issue, please see the answer here: What does it mean if console.log(4) outputs undefined in Chrome Console? but TL;DR you're just seeing the 'undefined' return from console.log(), because it has no return value. It shouldn't be an issue once you're not working in the console.
As for how you have 2 separate objects both called obj, I don't understand, as other said in the comments, please post the full code so we can see how this is being used/generated.
Also for clarification it looks like you're working with JavaScript objects, not JSON, similar but not the same.

Access object property

How i can select the count(user) from the tab object?
var tab =
[
{ id: '1', 'count(user)': 11 },
{ id: '2', 'count(user)': 31 },
{ id: '3', 'count(user)': 3 }
]
This prints 2:
console.log(tab[1].id)
but this gives me an error:
console.log(tab[1].count(user))
ReferenceError: user is not defined
How can I fix this?
Like this:
alert(tab[1]["count(user)"]);
Here is an example: JSFiddle
By the way, while the JSON in your example technically works, it is not formatted in a "best practice" way. Parameter names should have quotes around them:
{ 'id': '1',...
And parameter names should be valid JavaScript variables names, ie., no parenthesis, brackets, etc. This would be a more acceptable name:
'count_user': 11
Then you would not have had an issue using
console.log(tab[1].count_user)

Categories