I want to loop through the JSON I have below with the given JavaScript
{
"jsonUrl": "/testUrl",
"data": {
"country":"US",
"company":"ABC",
"items":[
{
"id": "1",
"id2": "12345",
"total": 1
},
{
"id": "2",
"id2": "23456",
"total": 2
}
]
}
}
I've tried the following but I've had no luck.
for (var key in json) {
if (json.hasOwnProperty(key)) {
alert(json[key]);
}
}
When doing this, the alert displays [object][object]. I don't get the actual data inside the object.
Firstly, don't use alert to watch the contents of the object in this case. When you use alert and you pass object in it, interpreter use toString method on this object. And the result of it is [object Object] construction. You can use JSON.stringify there.
How exactly you parse json? You can do this with JSON.parse.
Also, to not check if object has property with hasOwnProperty method you can use Array.prototype.forEach:
yourArrayData.forEach(function () {
console.log(JSON.stringify(value));
});
Also you can use for-of (only ES6+):
for (let value of yourArrayData) {
console.log(JSON.stringify(value));
}
A better option is to use the Object.keys() function to get the keys, then iterate to get your info.
The JSON object you are trying to loop through is several levels deep, and therefore you can't simply iterate over the keys and take their values (which in this case are also objects with keys). Depending on what information you want to retrieve, you will have to act differently. If you know the structure in advance, you can iterate over theObject.data.items using a for loop, or if you simply want to get to the the end of the JSON object, you can set up a queue:
let queue = [jsonObject];
while (queue.length > 0) {
var objectToEvaluate = queue.shift();
for (var key in objectToEvaluate) {
if (objectToEvaluate.hasOwnProperty(key)) {
if (typeof objectToEvaluate[key] === 'object') {
queue.push(objectToEvaluate[key]);
}
else {
// do something with the objectToEvaluate[key]
}
}
}
}
There are a few things to look out for with a queue. If it's possible for circular references ({a: b, b: a}), then you will need to keep track of which 'nodes' have been checked already. There are also some false positives that go along with checking whether the typeof is an object. I'd suggest reading more up on queues enter link description here
Related
Sample JSON data:
{
"assignments": [{
"date": "2022-04-01",
"lName": "lastname",
"uId": "12345",
"uCode": "LName1",
"fName": "FName1 ",
"aName": "AsignmentName1",
"aId": "998"
}]
}
I'd like to filter the following data to get a specific element's contents based on searching for an assignment name.
For instance in SQL like terms
Select * FROM assignments WHERE `aName` = 'AssignmentName1'
I'm sure this is simple but having trouble with methods for how to accomplish it.
Thanks
I am new here, but if you have access to modern day JavaScript, I would do something like:
const data = JSON.parse('{"assignments":[{"date":"2022-04-01","lName":"lastname","uId":"12345","uCode":"LName1","fName":"FName1 ","aName":"AsignmentName1","aId":"998"}]}';
const yourMatch = data.assignments.find(c => c.aName === 'AssignmentName1');
Since data.assignments is an array, you can call the find() function on it. This functions takes a 'search'-function/lambda as argument.
This search function basically takes an element and decides, whether it is the one you search for, or not aka it returns a boolean.
In my example the arrow function is c => c.aName === 'AssignmentName1', which is shorter and easier to read than a normal function definition. (You can call c whatever you want, it's just cleaner this way.)
You can exchange find() with filter(), if you accept multiple results and not just the first one.
You first have to parse the JSON string:
const parsedJSON = JSON.parse(jsonString);
The object returned is contains all the data from your JSON string. To access the assignments array you can use dot notation.
const assignments = parsedJSON.assignments;
If you don't need to support old browsers, ES6 has a handy function for finding the value in an object. Use the "find"-function and pass a function that returns true for the item you are looking for:
const selectedAssignment = assignments.find( (assignment)=> {
return assignment.aName=="AssignmentName2";
});
If you don't want to use ES6 you can use a for loop.
var assignments = JSON.parse(jsonString).assignments;
function getAssignmentWithName(name) {
for (var i = 0; i < assignments.length; i++) {
if (assignments[i].aName == name) {
return assignments[i];
}
}
return false;
}
var selectedAssignment = getAssignmentWithName("AssignmentName1");
In the code below, I can get a reference to the text000 object, but I need to capture its child array as my target payload. Once I have a reference to the key, how can I capture its children?
Full object is below:
activeItem = [{"dnd":{"index":0,"active":true,"group":"common","label":"Text (000)","type":"text"},
"json":{"schema":{"properties":{"text000":{"title":"Text (000)","type":"string"}},"required":["text000"]},"layout":[{"key":"text000","description":"","floatLabel":"auto","validationMessages":{"required":"Required"}}]}}]
To grab a reference to the "text000" key I'm using:
const myEl = Object.keys(this.activeItem.json.schema.properties); // points to text000
I need to pull that key's contents/children > {"title":"Text (000)","type":"string"} out to use it as my target payload for this operation.
The text000 element is dynamic so I need its reference, which is why I'm using the Object.keys() method to point to it.
Feel free to school me on the proper names to use to refer to these elements. For example, not sure exactly how to reference > {"title":"Text (000)","type":"string"} with respect to the key text000. Is that the key's "children", "value", "contents" or what?
UPDATE:
console.log('TRY: ', this.activeItem.json.schema.properties[0]);
// Returns undefined
console.log('TRY2: ', this.activeItem.json.schema.properties);
// Returns {"text000":{"title":"Text (000)","type":"string"}}
I need something to return:
{"title":"Text (000)","type":"string"}
SOLUTION thanks #jaredgorski:
const properties = this.activeItem.json.schema.properties;
const propertiesKeys = Object.keys(properties);
const propertiesKeysFirstVal = Object.keys(properties)[0];
const logProperties = properties[propertiesKeysFirstVal];
console.log('PROPERTIES KEYS:', propertiesKeys);
console.log(
'VALUES OF FIRST PROPERTIES KEY:',
propertiesKeysFirstVal
);
console.log('RESULT:', logProperties);
PROPERTIES KEYS: ["text000"]
wrux-wrux-form-builder.js:1782 VALUES OF FIRST PROPERTIES KEY: text000
wrux-wrux-form-builder.js:1783 RESULT: {title: "Text (000)", type: "string"}
You need to remember that activeItem is an array. As long as you include the index (in this case the first index, which is [0]), you can access the json property (or key) and continue down the chain to retrieve the values in text000.
The other trick here is that you're wanting to access the first key in properties, but you don't know the name of that key yet. So what you need to do is actually make an array of the keys and then find out the name of the first key in that properties object. To do this, you can use Object.keys(), a method which turns the keys of an object into an array. Once you have the name of this key, you only need to use bracket notation on the properties object to find the value for this key. I'll show you how this works in the snippet below.
Here are some references so that you can learn more about how this works:
MDN page on the Object.keys() method
Accessing JavaScript
object properties: Bracket notation vs. Dot notation
And here's the working example:
const activeItem = [
{
"dnd": {
"index": 0,
"active": true,
"group":"common",
"label":"Text (000)",
"type":"text",
"icon":"text_fields",
"fontSet":"material-icons",
"class":""
},
"json": {
"schema": {
"properties": {
"text000":{
"title":"Text (000)",
"type":"string"
}
},
"required":["text000"]
},
"layout":[
{
"key":"text000",
"description":"",
"floatLabel":"auto",
"validationMessages": {
"required":"Required"
}
}
]
}
}
]
// This is the dirty looking version:
const logPropertiesDirty = activeItem[0].json.schema.properties[Object.keys(activeItem[0].json.schema.properties)[0]]
console.log("First, the dirty version where we don't save anything to variables. Everything is laid out here.")
console.log('WHAT WE DID:', 'activeItem[0].json.schema.properties[Object.keys(activeItem[0].json.schema.properties)[0]]')
console.log('RESULT:', logPropertiesDirty)
console.log('=================================================')
// This is the cleaner version, using variables to store things as we go:
const properties = activeItem[0].json.schema.properties;
const propertiesKeys = Object.keys(properties);
const propertiesKeysFirstVal = Object.keys(properties)[0];
const logPropertiesClean = properties[propertiesKeysFirstVal];
console.log('Now, the cleaner version. We save some values to variables to make things more readable.')
console.log('PROPERTIES OBJECT:', properties)
console.log('PROPERTIES KEYS:', propertiesKeys)
console.log('NAME OF FIRST PROPERTIES KEY:', propertiesKeysFirstVal)
console.log('RESULT:', logPropertiesClean)
Regarding what to call these things, I've always thought of Objects as generally consisting of "key-value pairs". Keys can also be called properties and values can also be called contents (I guess).
myObject = {
key1: value1,
property2: contentsOfProperty2
}
At the end of the day, clear communication is all that counts! So, whatever names you come up with (as long as they make reasonable sense), I'm sure people won't be jerks about it unless they feel like they have something to prove.
You should be able to use Object.values over this.activeItem.json.schema.properties:
The Object.values() method returns an array of a given object's own enumerable property values, in the same order as that provided by a for...in loop (the difference being that a for-in loop enumerates properties in the prototype chain as well).
const object1 = {
a: 'somestring',
b: 42,
c: false
};
console.log(Object.values(object1));
// expected output: Array ["somestring", 42, false]
It is not supported across the map yet, but you should be able to load a polyfill if you need it.
I have an object that's nested like the example below.
var posts = {
"post1": {
"slug": "slug1",
"title": "title1",
},
"post2": {
"slug": "slug2",
"title": "title2",
}
};
I'm trying to write a for/in loop that will allow me to iterate through this object.
var testLoop = function () {
for (var prop in posts){
post = prop;
console.log(post); // Outputs post1 and post2
console.log(post.slug); // Outputs undefined
}
}
As seen above, I can't store and later access the properties of each iterated object. Only the name of the object is stored and logged. When I run typeof, I see that it's not even an object, it's just a string.
How can I correctly store each iterated properties as objects (post1, post2 etc.) during the loop so I can access their properties using dot notation?
When you use
for (var prop in posts){ ... }
It loops over the string keys in the posts object.
The main point here is that prop will be a string, and not an object like your current code is expecting.
As users in the comments suggested, because prop is the object key as a string, you need to use posts[prop] to refer to the actual object.
Here is some updated code.
var testLoop = function () {
for (var prop in posts){
post = posts[prop]; // ** this is line that needs to be modified **
console.log(post); // Outputs post object
console.log(post.slug); // this should work now
}
}
I want to delete __metadata where ever it appears .How to do that I searched this question but didn't get exact solution. hope you will help me out .
{
"__metadata":{
"uri":"asd",
"type":"DP_CART_SRV.DPCARTHeader"
},
"Dealer":{
"__metadata":{
"uri":"asd"
},
"CustomerNo":"",
"Name1":"",
"Name2":""
},
"Retailer":{
"__metadata":{
"uri":"asd"
},
"CustomerNo":"",
"Name1":"",
"Name2":""
},
"Cart":"0000000081",
"Type":"SH",
"CreatedOn":"/Date(1399420800000)/",
"ChangedOn":null,
"OrderId":"",
"OrderType":"",
"ReqDeliveryDate":"2014/05/31",
"OrderValue":"11.00",
"DocCurrency":"EUR",
"NetValue":"11.00",
"Freight":"0.00",
"Discount":"0.00",
"Tax":"0.00",
"Remarks":"Remarks",
"Items":{
"results":[
{
"__metadata":{
"uri":"asd"
},
"Cart":"0000000081",
"ItemNo":"000010",
"ProductID":"FAN_FG1",
"ItemDesc":"Finshed product FAN",
"Quantity":"1.000",
"Uom":"KAR",
"Price":"11.00",
"Currency":"EUR",
"Available":"",
"DeleteStatus":""
},
{
"__metadata":{
"uri":"",
"type":""
},
"DeleteStatus":"",
"Available":"",
"Currency":"",
"Price":"",
"Uom":"",
"Quantity":"",
"ItemDesc":"",
"ProductID":"",
"ItemNo":"",
"Cart":""
}
]
}
}
Here is a fun one. Not very obvious way how you can do it:
var result = JSON.parse(JSON.stringify(obj, function(key, value) {
return key !== '__metadata' ? value : undefined;
}));
It makes use of the replacer function JSON.stringify method accepts:
replacer
If a function, transforms values and properties encountered while stringifying; if an array, specifies the set of properties included in objects in the final string.
A detailed description of the replacer function is provided in the javaScript guide article Using native JSON.
However be aware that this is not intended JSON.stringify and JSON.parse usage. Also of course the result will no longer be the original object, but a new object.
Demo: http://jsfiddle.net/7Gj47/
I don't really know what you mean by "nested json attribute". The OP appears to be an object literal, which is the syntax used for JSON, however JSON is a string.
Anyhow, supposing you have JSON, it can be turned into an object using JSON.parse. You can then iterate over the object and remove any property with a certain name, and recursively remove properties from "nested" objects using a function like:
function removeProp(obj, propName) {
for (var p in obj) {
if (obj.hasOwnProperty(p)) {
if (p == propName) {
delete obj[p];
} else if (typeof obj[p] == 'object') {
removeProp(obj[p], propName);
}
}
}
return obj;
}
So if you have JSON (i.e. text representing an object), you can remove all instances of a particular property using something like:
var jsonText = '{ ... }';
var obj = JSON.parse(jsonText);
removeProp(obj, '__metadata');
jsonText = JSON.stringify(obj);
The function could take a third parameter that specifies if it should check nested objects or not.
So I have a JavaScript object like this:
foo = {
"one": "some",
"two": "thing",
"three": "else"
};
I can loop this like:
for (var i in foo) {
if (foo.hasOwnProperty(i)) {
// do something
}
}
Which will loop through the properties in the order of one > two > three.
However sometimes I need to go through in reverse order, so I would like to do the same loop, but three > two > one.
Question:
Is there an "object-reverse" function. If it was an Array, I could reverse or build a new array with unshift but I'm lost with what to do with an object, when I need to reverse-loop it's properties. Any ideas?
Thanks!
Javascript objects don't have a guaranteed inherent order, so there doesn't exist a "reverse" order.
4.3.3 Object An object is a member of the type Object. It is an unordered collection of properties each of which contains a primitive
value, object, or function. A function stored in a property of an
object is called a method.
Browsers do seem to return the properties in the same order they were added to the object, but since this is not standard, you probably shouldn't rely on this behavior.
A simple function that calls a function for each property in reverse order as that given by the browser's for..in, is this:
// f is a function that has the obj as 'this' and the property name as first parameter
function reverseForIn(obj, f) {
var arr = [];
for (var key in obj) {
// add hasOwnPropertyCheck if needed
arr.push(key);
}
for (var i=arr.length-1; i>=0; i--) {
f.call(obj, arr[i]);
}
}
//usage
reverseForIn(obj, function(key){ console.log('KEY:', key, 'VALUE:', this[key]); });
Working JsBin: http://jsbin.com/aPoBAbE/1/edit
Again i say that the order of for..in is not guaranteed, so the reverse order is not guaranteed. Use with caution!
Why there is no one has mentioned Object.keys() ?
you can get Array of Object's properties ordered as it is, then you can reverse it or filter it as you want with Array methods .
let foo = {
"one": "some",
"two": "thing",
"three": "else"
};
// Get REVERSED Array of Propirties
let properties = Object.keys(foo).reverse();
// "three"
// "two"
// "one"
// Then you could use .forEach / .map
properties.forEach(prop => console.log(`PropertyName: ${prop}, its Value: ${foo[prop]}`));
// PropertyName: three, its Value: else
// PropertyName: two, its Value: thing
// PropertyName: one, its Value: some
There is no way to loop through an object backwards, but if you recreate the object in reverse order then you are golden! Be cautions however, there is nothing that says the order of the object will stay the same as it changes and so this may lead to some interesting outcome, but for the most part it works...
function ReverseObject(Obj){
var TempArr = [];
var NewObj = [];
for (var Key in Obj){
TempArr.push(Key);
}
for (var i = TempArr.length-1; i >= 0; i--){
NewObj[TempArr[i]] = [];
}
return NewObj;
}
The just do the swap on your object like this-
MyObject = ReverseObject(MyObject);
The loop would then look like this-
for (var KeysAreNowBackwards in MyObject){
alert(MyObject[KeysAreNowBackwards]);
}
This answer is similar to a couple of the others, but some users might find the code below easier to copy-paste for their own uses:
Object.keys(foo).reverse().forEach(function(key) { console.log(foo[key]) });
For an object "foo" as described in the question, this code will output the object elements in reverse order: "else", "thing", "some"
You can use
Object.keys
One thing to take care of is that it returns a sorted list of keys (if the keys are numerical). You might need to change it accordingly.
a = {'d':'stack','l':'overflow','b':'out','a':'first','z':'empty'}
out = Object.keys(a).reverse()
console.warn("When key contains characters : "+out)
a = {'1':'stack','4':'overflow','2':'out','5':'first','3':'empty'}
out = Object.keys(a).reverse()
console.warn("When key is a numerical string : "+out)