Read a jsonObject recursively in javascript [duplicate] - javascript

This question already has answers here:
Check if a value is an object in JavaScript
(54 answers)
Closed 4 years ago.
I am trying to read a nested object as a key-value. I am using a recursive function to be able to enter each object and print its key-value. The problem is when I try to read a key-value where the value is null. It simply prints null, as if the key did not exist.
function readJsonObject(jsonObject){
for(var key in jsonObject){
if (typeof jsonObject[key] === 'object') {
readJsonObject(jsonObject[key]);
} else{
console.log(key + ": " + jsonObject[key]);
}
}
};
var text = '{ "employees" : [' +
'{ "firstName":"John" , "lastName":null },' +
'{ "firstName":"Anna" , "lastName":"Smith" },' +
'{ "firstName":"Peter" , "lastName":"Jones" } ]}';
var obj = JSON.parse(text);
readJsonObject(obj);
I should print:
firstName: John
lastName: null
firstName: Anna
lastName: Smith
firstName: Peter
lastName: Jones
But prints:
firstName: John
firstName: Anna
lastName: Smith
firstName: Peter
lastName: Jones
(Note that John's last name is not printed)
Any idea?

Here is a sample of a function that prints all the key : value for all objects recursively
function readJsonObject(jsonObject) {
if (Array.isArray(jsonObject)) {
for (var el of jsonObject) {
readJsonObject(el)
}
return
}
else if (typeof jsonObject === 'object' && jsonObject.constructor === Object) {
for (var key of Object.keys(jsonObject)) {
var value = jsonObject[key];
var toDisplay;
if (value && typeof value === 'object' && value.constructor === Object) {
toDisplay = readJsonObject(value);
} else if (Array.isArray(value)) {
toDisplay = JSON.stringify(value);
readJsonObject(value);
} else {
toDisplay = value;
}
console.log(key + ": " + toDisplay);
}
}
return jsonObject;
}
var text = '{ "employees" : [' +
'{ "firstName":"John" , "lastName":null },' +
'{ "firstName":"Anna" , "lastName":"Smith" },' +
'{ "firstName":"Peter" , "lastName":"Jones" } ]}';
var obj = JSON.parse(text);
console.log(readJsonObject(obj))
I handled Arrays as a special type, but please note there are other types that you maybe should check, since object encapsulate many other types, for instance null.

Related

how can I display the child object values(children) with the main object?

let state=["Karnataka","Andharapradesh","Tamilnadu"];
console.log(state);
document.write("<br>"+state);
for (i=0;i<=state.length-1;i++){
document.write(state[i]);
}
// -- question part--
let person = {
name: prompt("Your name"),
age: prompt("age?"),
spouse:prompt("spouse name"),
address: prompt("enter your address"),
children :{
child1: "kamal",
child2: prompt("name of the child"),
}
}
console.log(person);
for(let values in person){
document.write( "<br>" + values + ":" + person[values]);
}
// output
Karnataka,Andharapradesh,Tamilnadu
name:jashdk
age:khsald
spouse:kashdl
address:lksadlka
children:[object Object]
// it will display only main object values and the child value as children:[object Object]
You could make a tree search like this:
const treeSearch = (obj) => {
for(let values in obj) {
document.write("<br>" + values + ":" + obj[values]);
}
}
Then you can implement that by checking if the person object contains a object as one of it's keys values.
// Full Code
let person = {
name: prompt("Your name"),
age: prompt("age?"),
spouse:prompt("spouse name"),
address: prompt("enter your address"),
children :{
child1: "kamal",
child2: prompt("name of the child"),
}
}
const treeSearch = (obj) => {
for(let values in obj) {
document.write("<br>" + values + ":" + obj[values]);
}
}
for(let values in person){
if(typeof person[values] == "object") {
treeSearch(person[values]);
} else {
document.write( "<br>" + values + ":" + person[values]);
}
}
That should work.

Javascript: Unable to retrieve values in an object which has function

Using Javascript, I wrote this code to create an object:
let employee = {
emp_firstname: "Prasanta",
emp_lastname: "Banerjee",
emp_fullname: function(){
return (this.emp_firstname + " " + this.emp_lastname);
},
emp_id: 673630,
emp_horizontal:"QEA",
emp_vertical: "Insurance",
joining_date: "22/12/2017",
emp_salary : 13579,
emp_bonus : function(){
return (this.emp_salary*1);
}
};
Now, i'm interested in printing each property & its value so i wrote this code:
for (let eachEle in employee){
if(typeof eachEle=='string' || typeof eachEle=='number'){
console.log(eachEle + ":" + employee[eachEle]);
}
else if(typeof eachEle=='function'){
console.log(eachEle + ":" + employee.eachEle());
}
}
But, on executing, it works fine except for "emp_fullname" & "emp_bonus". Instead of showing the value, it shows me the function:
let employee = {
emp_firstname: "Prasanta",
emp_lastname: "Banerjee",
emp_fullname: function() {
return (this.emp_firstname + " " + this.emp_lastname);
},
emp_id: 673630,
emp_horizontal: "QEA",
emp_vertical: "Insurance",
joining_date: "22/12/2017",
emp_salary: 13579,
emp_bonus: function() {
return (this.emp_salary * 1);
}
};
for (let eachEle in employee) {
if (typeof eachEle == 'string' || typeof eachEle == 'number') {
console.log(eachEle + ":" + employee[eachEle]);
} else if (typeof eachEle == 'function') {
console.log(eachEle + ":" + employee.eachEle());
}
}
How am I supposed to retrieve the value for those two properties? I'm looking for answers using which I can modify the for...in loop & retrieve the value.
How am i supposed to retrieve the value for those two properties?
The function is the value of those properties. If you want to get the return value of the function, you have to call it.
Note that the typeof check you're doing in your for-in loop is unnecessary. The eachEle variable is the property name, not the property value. In a for-in loop, the name will always be a string. (Not all properties are named with strings, but for-in only covers the ones that are.)
You want to get the value of the property, check if it's a function, and if so call it:
for (let name in employee){
let value = employee[name];
if (typeof value === "function") {
value = employee[name]();
}
console.log(name + ":" + value);
}
Live Example:
let employee = {
emp_firstname: "Prasanta",
emp_lastname: "Banerjee",
emp_fullname: function(){
return (this.emp_firstname + " " + this.emp_lastname);
},
emp_id: 673630,
emp_horizontal:"QEA",
emp_vertical: "Insurance",
joining_date: "22/12/2017",
emp_salary : 13579,
emp_bonus : function(){
return (this.emp_salary*1);
}
};
for (let name in employee){
let value = employee[name];
if (typeof value === "function") {
value = employee[name]();
}
console.log(name + ":" + value);
}
You said you just wnated to change the loop, but another approach is to change the object definition to use an accessor property rather than an explicit function:
let employee = {
emp_firstname: "Prasanta",
emp_lastname: "Banerjee",
get emp_fullname() {
// ^^^ ^^
return (this.emp_firstname + " " + this.emp_lastname);
},
emp_id: 673630,
emp_horizontal:"QEA",
emp_vertical: "Insurance",
joining_date: "22/12/2017",
emp_salary : 13579,
get emp_bonus() {
// ^^^ ^^
return (this.emp_salary*1);
}
};
Then the loop doesn't have to check:
for (let name in employee){
console.log(name + ":" + employee[name]);
}
Live Example:
let employee = {
emp_firstname: "Prasanta",
emp_lastname: "Banerjee",
get emp_fullname() {
// ^^^ ^^
return (this.emp_firstname + " " + this.emp_lastname);
},
emp_id: 673630,
emp_horizontal:"QEA",
emp_vertical: "Insurance",
joining_date: "22/12/2017",
emp_salary : 13579,
get emp_bonus() {
// ^^^ ^^
return (this.emp_salary*1);
}
};
for (let name in employee){
console.log(name + ":" + employee[name]);
}
That works because when you get the value of an accessor property, its accessor function is run behind the scenes and that function's return value is provided as the property value.
You need to check the type of value, eachEle is value of key which for your object is always string.
let employee = {
emp_firstname: "Prasanta",
emp_lastname: "Banerjee",
emp_fullname: function() {
return (this.emp_firstname + " " + this.emp_lastname);
},
emp_id: 673630,
emp_horizontal: "QEA",
emp_vertical: "Insurance",
joining_date: "22/12/2017",
emp_salary: 13579,
emp_bonus: function() {
return (this.emp_salary * 1);
}
};
for (let eachEle in employee) {
if (typeof employee[eachEle] == 'string' || typeof employee[eachEle] == 'number') {
console.log(eachEle + ":" + employee[eachEle]);
} else if (typeof employee[eachEle] == 'function') {
console.log(eachEle + ":" + employee[eachEle]());
}
}
Two things you need to change
You need to check for the value of element for string, number and function and not the key
While executing the function you need to use the brackets notation since its a dynamic key
let employee = {
emp_firstname: "Prasanta",
emp_lastname: "Banerjee",
emp_fullname: function(){
return (this.emp_firstname + " " + this.emp_lastname);
},
emp_id: 673630,
emp_horizontal:"QEA",
emp_vertical: "Insurance",
joining_date: "22/12/2017",
emp_salary : 13579,
emp_bonus : function(){
return (this.emp_salary*1);
}
};
for (let key in employee){
let eachEle = employee[key];
if(typeof eachEle=='string' || typeof eachEle=='number'){
console.log(key + ":" + employee[key]);
}
else if(typeof eachEle=='function'){
console.log(key + ":" + employee[key]());
}
}
Your mistakes are:
1. You wrote: typeof eachEle insted of: typeof employee[eachEle]:
2. The execute is: employee.eachEle() insted of employee[eachEle](). eachEle is a string.
let employee = {
emp_firstname: "Prasanta",
emp_lastname: "Banerjee",
emp_fullname: function(){
return (this.emp_firstname + " " + this.emp_lastname);
},
emp_id: 673630,
emp_horizontal:"QEA",
emp_vertical: "Insurance",
joining_date: "22/12/2017",
emp_salary : 13579,
emp_bonus : function(){
return (this.emp_salary*1);
}
};
for (let eachEle in employee){debugger
if(typeof employee[eachEle]=='string' || typeof employee[eachEle]=='number'){
console.log(eachEle + ":" + employee[eachEle]);
}
else if(typeof employee[eachEle]=='function'){
console.log(eachEle + ":" + employee[eachEle]());
}
}
In your for loop, you iterate over the keys in the object, and those will never be objects. Instead, you should retrieve the item before checking its type.
for(let key in employee){
let value = employee[key];
if(typeof value=='string' || typeof vlaue=='number'){
console.log(key + ":" + value);
}
else if(typeof value=='function'){
console.log(key + ":" + value());
}
}

Looping through 'layered' javascript dictionary

I'm trying to create a dictionary (I think that's the best option...) for setting up a type of address book. The idea is to return something like
contacts = {"Bruce Wayne":{"phone number":'123-456-7890', "car":"All of them"}, "Alfred":{"phone number" :'987-654-3210', "car": "limo"}, "Clark Kent":{"phone number":'951-753-8520', "car":"None, flying works."}}
This works. I can do say console.log(contacts["Bruce Wayne"]) and it returns:
{ 'phone number': '123-456-7890', car: 'All of them' }
Doing console.log(contacts["Bruce Wayne"]["phone number"]) correctly returns
123-456-7890
However, I can't figure out how to loop through each person, and then each person's phone number and car.
Using this:
for (const[key, value] of Object.entries(contacts)){
console.log(contacts[key]);
}
just returns
[object Object]
[object Object]
[object Object]
I'm trying to get (psuedo code)
[First key], [key] is [value], [key] is [value]
Bruce Wayne, phone number is 123-456-7890, car is All of them
Alfred, phone number is 987-654-3210, car is limo
Edit: I also tried
for (var person in contacts){
console.log(contacts[person])
}
which also returns [object Object]...
try this:
for (let i in contacts) {
console.log(i + ',' + JSON.stringify(contacts[i]).replace(/\":\"/g, ' is ').replace(/["{}]/g, ''));
}
or
let contacts = { "Bruce Wayne": { "phone number": '123-456-7890', "car": "All of them" }, "Alfred": { "phone number": '987-654-3210', "car": "limo" }, "Clark Kent": { "phone number": '951-753-8520', "car": "None, flying works." } }
function consoleObj(obj, separator, attrIntro) {
let result = '';
for (let name in obj) {
result += name + separator;
for (let attr in obj[name]) {
result += attr + attrIntro + obj[name][attr] + separator;
}
result += '\n';
}
return result;
}
console.log(consoleObj(contacts, ',', ' is '));
or this
function consoleObj(obj, separator, attrIntro) {
return Object.keys(obj).reduce(function(result, name) {
result += name + separator;
Object.keys(obj[name]).forEach(function(attr) {
result += attr + attrIntro + obj[name][attr] + separator;
});
result += '\n';
return result;
}, '');
}
console.log(consoleObj(contacts,',',' is '));
Your for..of loop is giving you the name and the object with the properties, so you need to change how you access the "phone number" and "car" to details['phone number'] etc...
const contacts = {"Bruce Wayne":{"phone number":'123-456-7890', "car":"All of them"}, "Alfred":{"phone number" :'987-654-3210', "car": "limo"}, "Clark Kent":{"phone number":'951-753-8520', "car":"None, flying works."}}
// join an object
const joinObject = (obj, glue = 'is', joiner = ', ') =>
Object.keys(obj)
.map(k => `${k} ${glue} ${obj[k]}`)
.join(joiner)
// fixed string
for (const [name, details] of Object.entries(contacts)) {
console.log(`${name}, phone number is ${details['phone number']}, car is ${details['car']}`);
}
// dynamic property description
for (const [name, details] of Object.entries(contacts)) {
console.log(name + ' ' + joinObject(details))
}

Recursion with Javascript on JSON data

So, I have this function.
function makeContent(jsonData) {
var aProperty,
containerType,
contentContainerName,
containerIdentifier,
containerComment,
theContent;
console.log("jsonData = ");
console.log(jsonData);
var madeContent;
for (aProperty in jsonData) {
console.log("Working on property " + aProperty);
console.log("With value of ");
console.log(jsonData[aProperty]);
switch (aProperty) {
case "containerType": {
containerType = jsonData[aProperty];
break;
}
case "contentContainerName": {
contentContainerName = jsonData[aProperty];
break;
}
case "containerComment": {
containerComment = jsonData[aProperty];
break;
}
case "containerIdentifier": {
containerIdentifier = jsonData[aProperty];
break;
}
case "itemContent": {
theContent = jsonData[aProperty];
break;
}
}
}
if (typeof theContent !== 'undefined') {
console.log("theContent =");
console.log(theContent);
if (theContent.hasOwnProperty) {
if (madeContent != 'undefined') {
madeContent = makeContent(theContent);
madeContent = "<" + containerType + " " + containerIdentifier + "=\"" + contentContainerName + "\">" + madeContent + "</" + containerType + ">" + containerComment;
}
} else {
madeContent = "<" + containerType + " " + containerIdentifier + "=\"" + contentContainerName + "\">" + theContent + "</" + containerType + ">" + containerComment
console.log(madeContent);
console.log("Else statement");
}
}
return madeContent;
}
My trouble doesn't start until after the recursive call. For some reason after I call the makeContent() again in a recursive way, in the for loop to go through the properties in the object, I get 0 for the aProperty.
The JSON Data:
{
"contentContainerName" : "footer-bgcontent",
"containerType" : "div",
"containerIdentifier" : "id",
"containerComment" : "<!-- End #footer-bgcontent-->",
"itemContent" : [
{
"contentContainerName" : "footer",
"containerType" : "div",
"containerIdentifier" : "id",
"contentComment" : "<!-- End #footer -->",
"itemContent" : [
{
"contentContainerName" : "footerLink",
"containerType" : "a",
"containerIdentifier" : "id",
"contentTag" : ""
},
{
"contentContainerName" : "footerContent",
"containerType" : "div",
"containerIdentifier" : "id",
"contentTag" : "<div id=\"footerContent\"></div><!-- End #footerContent-->",
"itemContent" : [
{
"contentContainerName" : "createdBy",
"containerType" : "p",
"containerIdentifier" : "id",
"contentTag" : "<p id=\"createdBy\"></p>",
"itemContent" : "Created by: Patrick McAvoy"
},
{
"contentContainerName" : "lastModified",
"containerType" : "p",
"containerIdentifier" : "id",
"contentTag" : "<p id=\"lastModified\"></p>",
"itemContent" : "Last Modified: "
},
{
"contentContainerName" : "copyright",
"containerType" : "p",
"containerIdentifier" : "id",
"contentTag" : "<p id=\"copright\"></p>",
"itemContent" : "Copright"
}
]
}
]
}
]
}
Then the output
jsonData =
footer.js:51
Object
footer.js:55Working on property contentContainerName
footer.js:56With value of
footer.js:57footer-bgcontent
footer.js:55Working on property containerType
footer.js:56With value of
footer.js:57div
footer.js:55Working on property containerIdentifier
footer.js:56With value of
footer.js:57id
footer.js:55Working on property containerComment
footer.js:56With value of
footer.js:57<!-- End #footer-bgcontent-->
footer.js:55Working on property itemContent
footer.js:56With value of
footer.js:57[
Object
]
footer.js:83theContent =
footer.js:84[
Object
]
footer.js:50jsonData =
footer.js:51[
Object
]
footer.js:55Working on property 0
footer.js:56With value of
footer.js:57
Object
footer.js:38Made content:
footer.js:39<div id="footer-bgcontent">undefined</div><!-- End #footer-bgcontent-->
I'm unsure if this is causing your problem, but this line is wrong:
if (theContent.hasOwnProperty)
.hasOwnProperty is a method of every object/type in JS, so the test above is always true and so your code will always recurse, even if .itemContent is a string.
In any event, the code is unnecessarily complicated - there's no need to iterate through all the properties and test each key - just assign them directly to the required variables!
I believe the below code replicates what you're trying to do and is much shorter!
function makeContent(data) {
var type = data.containerType || 'div',
name = data.contentContainerName || '',
id = data.containerIdentifier || 'id',
comment = data.containerComment || '',
content = data.itemContent || '';
if (Array.isArray(content)) {
content = content.map(makeContent).join('');
}
return '<' + type + ' ' + id + '="' + name + '">' + content +
'</' + type + '>' + comment;
}
where the || 'foo' ensures the strings are assigned default values if not specified.
See http://jsfiddle.net/alnitak/rmTTg/ - NB: this code does nothing with the contentTag proeprty which is also unused in your own code.

Iterating json array in javascript

after looking through a lot of similar questions on SO, I still can't iterate my json structure. How can I reach the value (key) of my inner array?
var data = {"User1":{"Service1":2,"Service2":1},"User2":{"Service3":1}}
for(var user in data) {
document.write(user + ': ')
for(var service in data[user]){
document.write(service + ': ' + user[service])
}
document.write("<br />")
}
This prints:
User1: Service1: undefined Service2: undefined
User2: Service3: undefined
And I'd like it to print
User1: Service1: 2 Service2: 1
User2: Service3: 1
Is javascript enough or do I need jQuery?
Thanks in advance!
var data = {
User1: {
Service1: 2,
Service2: 1
},
User2: {
Service3: 1
}
};
for (var user in data) {
console.log("User: " + user);
for (var service in data[user]) {
console.log("\tService: " + service + "; value: " + data[user][service]);
}
}
Replace console.log with document.write or whatever.
document.write(service + ': ' + data[user][service])

Categories

Resources