Javascript string/object/array confusion with JSON - javascript

I'm having a Laravel backend return some errors via Validator. These errors are passed through a HTTP response made by angular, and returned in JSON format.
The object is structured as seen below:
That name object has a value, which is the actual message that I'm after.
Currently, using loops etc., I can only get the name of the array (name) as a string...
I sometimes get multiple arrays within this error object, and I won't always know their names, so how may I retrieve that 0-index value in each of them, in a loop?
Thanks for any help.
Edit #1
Looping through it like this:
for(var err in res.data.errors){
console.log(Object.err[0][0]);
}
Gives me a Cannot get [0] index of undefined

How about this:
let errors = Object.values(response.data.errors);
// errors is now an array of arrays containing the validation errors
errors.forEach( (errorArray) => {
console.log(errorArray[0]);
} );
Another approach would be using Object.keys() instead of values. This is similar to what you already tried, where you get the name of the error property as a string, and then use it to access each error array:
let keys = Object.keys(response.data.errors);
keys.forEach( (errorKey) => {
console.log('error type', errorKey);
let errorArray = response.data.errors[errorKey];
console.log(errorArray[0]);
} );

Related

How to drill into a JSON object to get the arrays when what should work doesn't

So, I have a similar situation as with this question which "SHOULD" work but doesn't
How can I access and process nested objects, arrays or JSON?
My JSON is basically this... reduced for brevity.
NOTE:
"{"message": [{"id":"1","element1":"Something","element1":"Something"},{"id":"2","element1":"Something","element1":"Something"}],"status": "success"}"
What happens is that if I select response coming from the API, I get the entire JSON.
If I type: response.message, I get UNDEFINED. That makes absolutely no sense.
This is what it looks like in sessionStorage:
I just want to do what I've always done: response.message or response.whatever to just give me what's "INSIDE" message and for some reason, no matter what I do, it's not working.
Here's the part of the code where I get the response with message
globalService.commonService('getData', reqPkg).then((response) => {
$scope.theReport.data = JSON.parse(response);
});
if I do this I get undefined
$scope.theReport.data = JSON.parse(response.message);
I've tried JSON.stringify too, same result.
This is from a previous question which works fine and is in deed just the Objects from the Array of Objects.
const arrResult = Object.keys(objCount).map(k => ({'name': k, 'displayName': k, 'count': objCount[k] }));
$scope.theReport.data = JSON.parse(response).message; to get all entries from message into $scope.theReport.data.
Your response is a string, so parse the response and just grab the message key from that.

Getting empty snapshot when reading Firebase Database in Javascript?

I have the following database structure:
I am trying to get the list of values under registrationTokens to then execute an FCM notification to the list of tokens. But the output to the console is empty even though there is a token under the child node. Am I missing something here?
Console output:
registrationTokens [ '0' ]
Part of my JS function code below:
return admin.database().ref('/fcmtokens/' + toId + '/registrationTokens').once('value').then((userTok) => {
const registrationTokens = Object.keys(userTok.val());
console.log('registrationTokens', registrationTokens);
});
Your console output is exactly as I'd expect. You've read the following children from the database:
0: 'c4P...'
Then you asked for the keys of that object to be printed, as returned by Object.keys(). Note that this key a key/value pair: the key is 0 and the value is 'c4P...'. This means that the following call:
Object.keys(userTok.val());
Is going to return an array of keys of the children. Since there is one child with a key of 0, you get this array:
[ '0' ]
So, I'd say your function is working exactly as you coded it. If you want the token values instead, try this:
If you want to tokens for each key instead, maybe you should use Object.values() instead:
Object.values(userTok.val());
I'd expect that to return an array of all the values associated with they keys.

Indexing into mongoose.model for an array is returning undefined

I've created a simple table (document?) in mongoDB.
I'm using Node and Mongoose to connect to it.
In my method, I am calling model.find({}) to retrieve all records and then iterating over them to find one that I want (this is within a loop - I'm thinking it will be more efficient to hit the DB once, and then process in memory to avoid connecting to the database each time).
When I console.log the match, I'm getting the full object printed out. When I print out one property, however, it's listing it as undefined. This property is an array, and it's happening for another property that has an array that I added as a test. What am I missing here?
Here's my code snippet:
Documents.find({}).then(docsData => { // Documents is my model
docs.entries.forEach(entry => { // docs.entries is the collection I want to match to
const match = docsData.find(
doc => doc['dropboxId'] == entry['id']
);
if (match) {
entry['tags'] = match.tags;
console.log('match tags', match.tags); // this prints out undefined
console.log('match', match); // this prints out the object with tags
}
Any ideas?
match is a Mongoose document which is different from normal JS object. I guess you need to do:
entry['tags'] = match.get('tags');

iteration of a JSON containg objects

I am trying to write a function that takes pokemon’s name as an argument and find out which all pokemon have that name in their “next_evolution” field
Consider the following JSON dataset -
visit https://raw.githubusercontent.com/Biuni/PokemonGO-Pokedex/master/pokedex.json
now for that, I've written the following function:
var infoOfPokemon = function(nameOfPokemon,allPokemon){
for(x in allPokemon){
if(allPokemon[x].next_evolution.includes(nameOfPokemon)){
console.log('pokemons found: '+allPokemon[x].name)
} else{
null
}
}
}
var nameOfPokemon =prompt('enter the name of Pokemon')
infoOfPokemon(nameOfPokemon,pokemonData.pokemon)
but it is returning an error which says
Uncaught TypeError: Cannot read property 'includes' nextEvolution.js:4090 of undefined
One or more of your pokemon does not have a 'next_evolution' field set (for example, the one with id 3 in your file). Hence allPokemon[x].next_evolution evaluates to undefined and you cannot read 'includes' on that.
Check for the existence of next_evolution, first.
if (allPokemon[x].next_evolution &&
allPokemon[x].next_evolution.includes(nameOfPokemon)) { ...
and find out which all pokemon have that name in their “next_evolution” field
That should make you think of filter. You want to filter the list of pokemon to find the matching ones.
But, as already pointed out, you need to be able to return false in your filter predicate if the pokemon you're testing does not have a next_evolution field. You can do that via testing, as suggested in another answer: pokemon.next_evolution && pokemon.next_evolution.includes..., or you can default it, as below: (pokemon.next_evolution || []).includes...
(Note though that both you original and that answer miss a step, which is to then collect that name properties from those next_evolution values.
So here is a simple function which should filter the list to find the correct items. To use it with a call to your API, I wrap it in a fetch call, and simply console.log the results. Obviously, you might well have other ways to call it.
const infoOfPokemon = (name, all) => all.filter(pokemon =>
(pokemon.next_evolution || []).map(p => p.name).includes(name)
)
fetch('https://raw.githubusercontent.com/Biuni/PokemonGO-Pokedex/master/pokedex.json')
.then(resp => resp.json())
.then(allPokemon => console.log(
infoOfPokemon('Butterfree', allPokemon.pokemon) //~> [{Caterpie}, {Metpod}]
))
You cannot use includes function directly on array having objects instead of single object. It will give false as output.
For e.g:
var pets = [{'name':'cat'},{'name':'dog'},{'name':'bat'}];
console.log(pets.includes("cat")) //false
This results in false always.
Proper way is to use a map to get a particular object field on which you want to use includes function.
e.g:
var pets = [{'name':'cat'},{'name':'dog'},{'name':'bat'}];
console.log(pets.map((obj)=> obj.name).includes("cat")); //true
In Your case first see if allPokemon[x].next_evolution is undefined or not (i.e next_evolution key is present or not)
code becomes:
if (allPokemon[x].next_evolution &&
allPokemon[x].next_evolution.(obj)=> obj.name).includes(nameOfPokemon)) { ...

How to get the key of an array object?

Given a JSON respond to a form I need to parse through the JSON elements to find error messages with their associated element the error is tied to.
The data is returned in JSON format with the error messages as the last variable pair looking like this:
"invalid":[{"field1":"Field 1 is required"}]
This ends up having an object/array for each error showing the item's name(key) along with the associated error for that field. Given that my error handling form is unaware what the key names will be how do I go about getting both the key and the value out of this object/array?
I'm using dojo on this project and I'm not familiar with it at all so I've been attempting to use dojo functions when possible if something exists that can handle this. Currently there is where I am :
var retObj = dojo.fromJson(ioargs.xhr.responseText);
dojo.forEach(retObj.invalid, function(entry,i){
console.debug(entry);
});
The console output is:
Object { field1="Field 1 is required"}
My goal is to pull out the value "field1" so I know which input field this error is assigned to, then to assign the value of field1 to that error field.
Thanks!
Dunno a single thing about Dojo, but you're looking for a pretty basic for in loop.
var retObj = dojo.fromJson(ioargs.xhr.responseText),
invalids = retObj.invalid[0],
res = {}; //here will be your final key=>value
for (var key in invalids) {
res[key] = invalids[key];
}
http://jsfiddle.net/DgXkq/
You might also be interested in https://stackoverflow.com/search?q=%5Bjavascript%5Dparsing+json
There is no way to find the key of an object if you don't have access to the parent object. I believe the best solution in this case would be to massage the JSON to pass more meaningful information to the validator, that is, an object with two properties, fieldName and errorMessage.
// Returns the name of an object's first key
function getKeyName(obj) {
for (var prop in obj) {
return prop;
}
}
// This is the response from the server
var response = { "invalid":[{"field1":"Field 1 is required"}] };
// This is going to be the massaged array that
// contains more meaningful information.
var invalids = [];
for (var i=0; i < response.invalid.length; i++) {
var obj = response.invalid[i];
var key = getKeyName(obj);
invalids.push({fieldName: key, errorMessage: obj[key]})
}
Now invalids contains an array of more meaningful error message objects like
invalids = [{fieldName: 'field1', errorMessage: 'Field 1 is required'}]
Just pass that object to your validation routine. If possible, I would change the server code to return error messages in the format I suggested so you don't have to do extra work.

Categories

Resources