How to access nested values in JSON response as an array - javascript

Using const token = response.json().token; I am able to get the following JSON:
{
"token": "*********",
"roles": [
{
"id": 4,
"name": "User",
"pivot": {
"user_id": 1,
"role_id": 4
}
}
]
}
I want to be able to access the names within the roles as an array.

If you just want to access the array of roles, assuming you're using a traditional response object, you can just access it the way other users have stated:
var roles = response.json().roles
As I reread the question and comments, I get the idea that the user wants to access the names within the roles as as list. Assuming so, the map function will do this nicely:
// Assuming we store response in "data"
var data = response.json();
var names = data.roles.map(function(role){return role.name});
console.log(names);
// Then "names" will look like ["User",...]
In a nutshell, map will walk the array it's called against and run the provided function against it, with the first argument being the current value it sees in the array. This function can be defined on the fly as above, or predefined and passed if the logic is complex or reused.
This is a very common use for Map, and its sibling, Reduce. Both are often used for distilling complex, variable-length data down to a simpler form.
Map documentiation:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map
Update: It would appear the original question was asked regarding ES6, so here's the "proper" ES6 version with proper declarations and arrow funcs:
// Assuming we store response in "data"
const data = response.json();
const names = data.roles.map(role => role.name);
console.log(names);
// Then "names" will look like ["User",...]

Related

Angular/Javascript array find method

I have started to learn angular recently. I came across a code as follows.
Consider this.members as an array of objects. There is an object which has the username bob. I am trying to get that particular object using the below code.
const data = this.members.find(x=>x.userName===username);
So there an object inside the array and I have an object stored in my const data, My doubt is that will both (the object in the array and the object in the const data ) have the same memory address. If someone could answer why changing the const data is also getting reflected in the this.members array. It would be a great help. You can also share some resources if I need to go through them to understand them better.
To shortly answer your question, yes. The data object will have a reference to the object inside this.members.
If you want to prevent that, there are multiple ways I'm sure, but one of them is to use Object.assign.
Example:
let data: any = {};
Object.assign(data, this.members.find(u => u.username === 'bob'));
console.log(this.members); // For example: [{username: 'bob'},{username: 'randy'}]
data.username = 'alex';
console.log(this.members); // Still shows [{username: 'bob'},{username: 'randy'}]
console.log(data); // {username: 'alex'}
Notice here that I am using TypeScript since you mentioned you're working with Angular.
When using Object.assign, a copy of the enumerable properties will be made and assigned to your variable without referencing the source.
See MDN Docs for more details.
Another simple way is to use the spread operator.
let data: any = {};
const foundUser = this.members.find(u => u.username === 'bob');
if (foundUser) {
data = {...foundUser};
}
This will create a new object with the properties from the foundUser.
You can easily try it out.
const members = [
{ username: 'bob' },
{ username: 'daniel' },
];
const data = members.find(x=>x.username==='bob');
data.username = 'bobby';
console.log(members);
That prints
[ {
"username": "bobby" }, {
"username": "daniel" } ]
So yes, changing data will change the array.
The answer for this question is that Arrays in javascript are mutable which means they are reference type which means when I encounter the below line
const data = this.members.find(x=>x.userName===username);
const data will have the same memory location as that of bob in the array. As we all know that if we change data at a memory location every variable/object referring to that memory location will also change as they all point to the same memory location. Hence the array gets updated even though I assign a part of the array and make changes to that part alone.
Note: The above was my expected behavior. if you want the opposite behavior like if you need the const data and this.members to be independent you can use
Copy Array
or you can refer to Maher's answer in the same page.

How do I extract specific values from the JSON response in Postman using a test?

I need to be able to parse through the JSON results from a Postman response to just pull out the name value in the console output. My JSON looks like this:
"total_count": 7,
"entries": [
{
"type": "collaboration",
"id": "21829111111",
"created_by": null,
"created_at": "2020-03-24T05:37:09-07:00",
"modified_at": "2020-03-24T05:37:09-07:00",
"expires_at": null,
"status": "accepted",
"accessible_by": {
"type": "group",
"id": "3085402",
"name": "Test",
"group_type": "managed_group"
Most of the examples I find are using extracted value to create a variable but I really just need a simple list I can copy and paste.
I've used this code to do something similar but I am not sure how to modify it for us with this data:
var response = JSON.parse(responseBody);
var usernames = response.map(function(account){
    return account.credentials.userName;
});
console.log(usernames);
Any help is appreciated.
Let's walk through it:
var response = JSON.parse(responseBody);
JSON.parse() is taking the JSON response in as a string, and converting it to a JS object, which will then be stored in response.
response.map(...)
The map() function is called on an array and takes a function as a parameter. It calls the function you provide it once for each element in the array that it's called on.
For your particular case, we'll need to modify this a little, since response is an object, rather than an array, and the value you're after, name, is nested in the entries array inside of response. To account for this, we're going to call map() directly on the nested array, and set it equal to a new variable to store the result, like this:
var names = response.entries.map(...);
Now, we can pass map() a function that will extract the name from each element in the entries array. Our function needs to accept the array element as a parameter, and return the extracted name so that map() can add it to the new array it's making.
function(entry) {
return entry.accessible_by.name;
}
In the end, we end up with this:
var response = JSON.parse(responseBody);
var names = response.entries.map(function(entry) {
return entry.accessible_by.name;
});
console.log(names);
This will output an array of names to your browser console. ["Test", ...]
Bonus:
With a little JavaScript syntactic sugar (specifically arrow functions), we can make the function code a little cleaner:
var response = JSON.parse(responseBody);
var names = reponse.entries.map(entry => entry.accessible_by.name);
console.log(names);

Access a nested array in Angular 6

So i am attempting to access an Array of objects within a JSON object. I have an API that i am grabbing data from. The API was initially an XML and i converted it to a JSON object, however one i have dashes in my element names. (dang), but i also want to pull from the list of products. Below is an example of the API structure.
The goal is to get the list of products from the API.
Thanks to PXLJoy i was able to come up with the following solution. Note: I am using RXJS 6, therefore everything is wrapped in a pipe.
public getData(): Observable<any> {
const cjData = this.http.get('/assets/json/name.json');
return cjData.pipe(map(res => res['cj-api'].products[0].product));
}
Accessing properties in JSON can be done with [] square brackets, these are often used for variable keys, i.e
const key = 'cj-api';
const obj = response[key];
or string keys, i.e
const obj = response['cj-api'];
With that said, based on your screenshot, you could get the products array by going:
// response is the object as shown in your screenshot.
response['cj-api'].products[0].product; // your target array

Generating Tree Structure from Flat Array in JavaScript (without using object references)

I'm trying to generate a tree structure in JavaScript from a flat array. This would usually be a fairly straightforward proposition - simply retain a 'stack' array with references to ancestor objects of the current working scope ordered by nesting depth - push a new element onto the stack when entering another nested level, and pop it off when leaving one, replacing the current working element with the object referenced by the (new) last array item.
Unfortunately this requires the capability to pass-by-reference, which JavaScript doesn't have (well, doesn't have in any meaningful way that I know how I could use for this problem.)
To give a bit of background, I'm trying to turn an arbitrarily long/complicated string containing nested XML-style (but not XML, so an XML parser can't be used instead) tokens into a structure similar to the one below:
Expected Input:
[
"<token>",
"<my non compliant token>",
"some text at this level",
"<some other token>",
"some more text",
"<yet another token>",
"more text",
"</yet another token>",
"blah!",
"</some other token>",
"</token>",
"more text"
]
Expected Output
[
{
"token": "<token>",
"children": [
{
"token": "<my non compliant token>",
"children": [
"some text at this level",
{
"token": "<some other token>",
"children": [
"some more text",
{
"token": "<yet another token>",
"children": [ "more text" ]
},
"blah!"
]
}
]
}
]
},
"more text"
]
To clarify - I'm not after an entire algorithm (but I'd be interested if you want to provide your implementation) - just a good method for maintaining current position in the outputted tree (or an entirely different/better way of generating tree objects!) Don't get too caught up on how the tokens work - they're not XML and for the purpose of the exercise could be formatted entirely differently.
Any input would be greatly appreciated!
Your strings look easy to parse. I think I would do something like this:
var stack = [];
var array = [];
for (var i in strings) {
var s = strings[i];
if (s.indexOf("</") == 0) {
array = stack.pop();
} else if (s.indexOf("<") == 0) {
var obj = {token: s, children: []};
array.push(obj);
stack.push(array);
array = obj.children;
} else {
array.push(s);
}
}
Idea #1
Here's an answer you probably weren't anticipating.
Looking at your expect output, I was wondering if it's easiest to just generate JSON and then eval it when you're done. No references at all.
When going through your flat array, you basically have three operations:
You add more data to the current object
You close off the current object
You create a new child object
You can do all three of those fairly easily by just appending the appropriate text onto a JSON string you're building as you iterate through your source array to literally just generate the text you show in your expected output. When done, run that JSON string through eval. You may need a few safety checks to verify that each array and object is closed properly if there are errors in the input, but it should work fine.
Idea #2
You can still use your stack array. I'm not sure exactly why you need to pass by reference, but you can just pass an index into the array around and have everyone modify the master copy of the array that way via index. Using local functions, the master array can be a common data value that is local to your main function, but essentially global to all your sub-functions so they can all shared access to it.
This would look something like this:
function ParseRawData(rawData)
{
var parentScopeArray = []; // main parent scope of objects
function processTag(x)
{
// you can access parentScopeArray directly here and
// and be accessing it by reference
}
// other code or local functions here
}
Idea #3
If you want to pass the array into a function and have the master copy modified (perhaps the reason you're thinking of pass by reference), the javascript design pattern is to pass the array in and return a modified array, replacing the entire original array with the modified one that is returned.

How do I add one single value to a JSON array?

I am kind of new to the world of interface, and i found JSON is amazing, so simple and easy to use.
But using JS to handle it is pain !, there is no simple and direct way to push a value, check if it exists, search, .... nothing !
and i cannot simply add a one single value to the json array, i have this :
loadedRecords = {}
i want to do this :
loadedRecords.push('654654')
loadedRecords.push('11')
loadedRecords.push('3333')
Why this is so hard ???!!!
Because that's an object, not an array.
You want this:
var = loadedRecords = []
loadedRecords.push('1234');
Now to your points about JSON in JS:
there is no simple and direct way to push a value
JSON is a data exchange format, if you are changing the data, then you will be dealing with native JS objects and arrays. And native JS objects have all kinds of ways to push values and manipulate themeselves.
check if it exists
This is easy. if (data.someKey) { doStuff() } will check for existence of a key.
search
Again JSON decodes to arrays and objects, so you can walk the tree and find things like you could with any data structure.
nothing
Everything. JSON just translates into native data structures for whatever language you are using. At the end of the day you have objects (or hashes/disctionaries), and arrays which hold numbers strings and booleans. This simplicity is why JSON is awesome. The "features" you seek are not part of JSON. They are part of the language you are using to parse JSON.
Well .push is an array function.
You can add an array to ur object if you want:
loadedRecords = { recs: [] };
loadedRecords.recs.push('654654');
loadedRecords.recs.push('11');
loadedRecords.recs.push('3333');
Which will result in:
loadedRecords = { recs: ['654654', '11', '3333'] };
{} is not an array is an object literal, use loadedRecords = []; instead.
If you want to push to an array, you need to create an array, not an object. Try:
loadedRecords = [] //note... square brackets
loadedRecords.push('654654')
loadedRecords.push('11')
loadedRecords.push('3333')
You can only push things on to an array, not a JSON object. Arrays are enclosed in square brackets:
var test = ['i','am','an','array'];
What you want to do is add new items to the object using setters:
var test = { };
test.sample = 'asdf';
test.value = 1245;
Now if you use a tool like FireBug to inspect this object, you can see it looks like:
test {
sample = 'asdf,
value = 1245
}
Simple way to push variable in JS for JSON format
var city="Mangalore";
var username="somename"
var dataVar = {"user": 0,
"location": {
"state": "Karnataka",
"country": "India",
},
}
if (city) {
dataVar['location']['city'] = city;
}
if (username) {
dataVar['username'] = username;
}
Whats wrong with:
var loadedRecords = [ '654654', '11', '333' ];

Categories

Resources