find and change properties with the value undefined - javascript

I have a nested javascript object called data. Is there any way to iterate through it and find all properties that have the value undefined and set it to a string, "undefined" insted. JSON doesnt validate if the property value is undefined in IE7. Thanks
{
"Target": "System",
"Systemoperation": "Buy-In",
"Systemorigin": "ABB",
"Subscriptionmode": "Maintain & Evolve",
"Evolveto": "800xA",
"Quoteselection": "Full Quote",
"Commitmenttimeframe": "3 years",
"codevalues": {
"Target": 100,
"Systemoperation": 110,
"Systemorigin": false,
"Subscriptionmode": 4,
"Evolveto": undefined,
"Quoteselection": "fullquote",
"Commitmenttimeframe": 3
},
"Route": [
"System",
"Buy-In",
"ABB",
"Maintain & Evolve",
"800xA",
"Full Quote",
"3 years"
],
"currentsystem": ""
}
Here is evolteto in codevalues undefined. Which does not validate (try http://jsonlint.com/).

If this is your data structure (nested objs):
data = {
a: undefined,
b:{
c: '1',
d: undefined
}
}
Then, this works for you
for (var items in data) {
if (data[items] === undefined) {
data[items] = 'undefined';
continue;
}
for (var i in data[items]) {
if (data[items][i] === undefined) {
data[items][i] = 'undefined';
}
}
}

A very crude search but works,
for(var prop in arr)
{
if(typeof arr[prop] === 'object')
{
for(var subprop in arr[prop])
{
if(typeof arr[prop][subprop] === 'undefined')
arr[prop][subprop] = "undefined";
}
}
}
http://jsfiddle.net/h27dp/1/ - JSON validator also validates the result obtained here as a "Good JSON"

function disp(j) {
for(var key in j) {
if(j.hasOwnProperty(key)) {
if(typeof j[key] === "object") {
disp(j[key]);
}
else {
if ( j[key] === undefined) {
j[key] = "undefined";
} // if undefined key
} // else
} // if hasOwnProperty
} // for
} // function
And then call it with
disp[data];

Related

Javascript - Traverse through the Json Object and get each item hierarchical key including nested objects and arrays

I want to get the values and keys including these as to any JSON objects as a generic method to use even for the complex objects
json
{
"timezone": 5.5,
"schedule": {
"type": "daily",
"options": {
"hour": 10,
"minute": 29
}
}
want the values and keys in hierarchical schema just like these
timezone - 5.5
schedule.type - daily
schedule.type.options.hour - 10
schedule.type.options.minute - 29
Also, I used this function can get the JSON objects all objects keys and values even in the nested arrays and objects in that
function iterate(obj) {
for (var property in obj) {
if (obj.hasOwnProperty(property)) {
if (typeof obj[property] == "object") {
iterate(obj[property]);
} else {
console.log(property , obj[property])
}
}
}
return obj;
}
PS - Also I
want to use this for arrays also
"dirs": [ { "watchDir": "Desktop/logs", "compressAfterDays": 50 }, { "watchDir": "Desktop/alerts", "timeMatchRegex": "(.*)(\\d{4})-(\\d{2})-(\\d{2})-(\\d{2})_(\\d{2})(.*)", }]
the output I want to be just like this
dirs[0].watchdir="Desktop/alerts"
dirs[1].watchDir="Desktop/logs"
const obj = { "timezone": 5.5, "dirs": [ { "watchDir": "Desktop/logs", "compressAfterDays": 50 }, { "watchDir": "Desktop/alerts", "timeMatchRegex": "(.*)(\\d{4})-(\\d{2})-(\\d{2})-(\\d{2})_(\\d{2})(.*)", }] ,"schedule": { "type": "daily", "options": { "hour": 10, "minute": 29 }, 'available': true } };
function iterate(obj, str) {
let prev = '';
for (var property in obj) {
if (obj.hasOwnProperty(property)) {
if (typeof obj[property] == "object") {
const s = isArray(obj) ? prev + str + '[' + property + ']' + '.' : prev + property + (isArray(obj[property]) ? '' : '.');
iterate(obj[property], s);
} else {
prev = (str != undefined ? str : '');
console.log(prev + property, '- ' + obj[property]);
}
}
}
return obj;
}
function isArray(o) {
return o instanceof Array;
}
iterate(obj);
Pass on the keys in the recursive call:
function iterate(obj, path = []) {
for (let property in obj) {
if (obj.hasOwnProperty(property)) {
if (typeof obj[property] == "object") {
iterate(obj[property], [...path, property]);
} else {
console.log(path, property , obj[property])
}
}
}
}

How to check if array has nested property with defined value

I have an array of complicated objects and arrays in javascript such as:
var array = [
{ "simpleProp": "some value" },
{ "booleanProp": false },
{
"arrayProp": [
{ "prop1": "value1" },
{
"prop2": {
"prop22": "value22",
"prop23": "value23"
}
},
{ "prop3": "value3" },
{ "booleanProp": true }
]
}
];
I have to know if there is a property with defined value in my array, such as:
function some(array, property, value) {
//some logic here
// return boolean
};
That is, for my source array the result of this:
var result = some(array, "booleanProp", true)
- must be TRUE.
I tried to use lodash function _.some(), but it returns false for my array, it appears _.some() can't find deeply nested properties.
It would be very cool if the function may support complicated object as source, not only array.
I'd appreciate any help, thanks.
You could use an iterative and recursive approach by checking the actual object and if the value is an object iterate the object's keys.
function some(object, property, value) {
return object[property] === value || Object.keys(object).some(function (k) {
return object[k] && typeof object[k] === 'object' && some(object[k], property, value);
});
}
var data = [{ simpleProp: "some value" }, { booleanProp: false }, { arrayProp: [{ prop1: "value1" }, { prop2: { prop22: "value22", prop23: "value23" } }, { prop3: "value3" }, { booleanProp: true }] }];
console.log(some(data, 'booleanProp', true)); // true
console.log(some(data, 'foo', 42)); // false
Above Solution is great but it is not working for Array.
So I've Modified it little bit and now it is working for both Arrays & normal properties. Even In Arrays element's placement can be anything.
const data = {
"names": [
{
"name": {
'homename': 'Raju',
'academisName': 'Rajpal',
'callingName': ['Raj', 'Rajpal', 'Raju']
},
"defaultName": "Raj"
}]
}
Code for Array:
const some = (object, property, value) => {
return _.isArray(value) && _.isEqual(_.sortBy(object[property]), _.sortBy(value)) || object[property] === value || Object.keys(object).some(function (k) {
return object[k] && typeof object[k] === 'object' && some(object[k], property, value);
});
}
const data = {
"names": [{
"name": {
'homename': 'Raju',
'academisName': 'Rajpal',
'callingName': ['Raj', 'Rajpal', 'Raju']
},
"defaultName": "Raj"
}]
}
const some = (object, property, value) => {
return _.isArray(value) && _.isEqual(_.sortBy(object[property]), _.sortBy(value)) || object[property] === value || Object.keys(object).some(function(k) {
return object[k] && typeof object[k] === 'object' && some(object[k], property, value);
});
}
console.log('Result 1', some(data, 'callingName', ["Raj", "Rajpal", "Raju"]));
console.log('Result 2', some(data, 'callingName', ["Rajpal", "Raj", "Raju"]));
<script src="https://cdn.jsdelivr.net/npm/lodash#4.17.15/lodash.js"></script>
Note: that value.sort() will mutate the arrays so I've used _.sortBy(value), same for object[property]
console.log(some(data, 'callingName',  ["Raj", "Rajpal", "Raju"]));
console.log(some(data, 'callingName', ["Rajpal", "Raj", "Raju"]));

Can't determine why an else if statement enters a condition that evaluates to false [duplicate]

This question already has an answer here:
If 'if' condition is false, statements do not execute in chrome, but execute in Firefox
(1 answer)
Closed 6 years ago.
Consider the following object o, and a function findEmpty that is supposed to print to the console properties which value is an empty array.
var o={
"StudentInfo": [{
"Name1": [{
"100": {
"a": "12"
}
}, {
"101": {
"a": "50"
}
}]
}, {
"Name2": [{
"102": {}
}, {
"103": {
"b": "50"
}
}]
}]
}
function findEmpty(obj)
{
for (var p in obj)
{
debugger;
var propValue = obj[p];
var condition = propValue && typeof propValue === 'object' && !Array.isArray(propValue);
if (Array.isArray(propValue) && propValue.length == 0) {
console.log('Property ' + p + ' has an empty array.');
}
else if (condition) {
findEmpty(propValue);
}
}
}
In debugging, the condition that the else if is to check renders false, but it keeps entering it. What is it that I am missing?
Update: during debugging, running an if/else in the console on the same boolean variable will execute the code for the false evaluation.
How can a propValue be an object and an array at the same time?
Shouldn't it be:
var condition = propValue && typeof propValue === 'array' && !Array.isArray(propValue);

Using JavaScript what's the quickest way to recursively remove properties and values from an object?

I need to find the fastest way to remove all $meta properties and their values from an object, for example:
{
"part_one": {
"name": "My Name",
"something": "123",
"$meta": {
"test": "test123"
}
},
"part_two": [
{
"name": "name",
"dob": "dob",
"$meta": {
"something": "else",
"and": "more"
}
},
{
"name": "name",
"dob": "dob"
}
],
"$meta": {
"one": 1,
"two": 2
}
}
Should become the following given that the $meta property could be at any point in the object so some form of recursion will probably be needed.
{
"part_one": {
"name": "My Name",
"something": "123"
},
"part_two": [
{
"name": "name",
"dob": "dob"
},
{
"name": "name",
"dob": "dob"
}
]
}
Any help or advice would be greatly appreciated!
Thank you!
A simple self-calling function can do it.
function removeMeta(obj) {
for(prop in obj) {
if (prop === '$meta')
delete obj[prop];
else if (typeof obj[prop] === 'object')
removeMeta(obj[prop]);
}
}
var myObj = {
"part_one": {
"name": "My Name",
"something": "123",
"$meta": {
"test": "test123"
}
},
"part_two": [
{
"name": "name",
"dob": "dob",
"$meta": {
"something": "else",
"and": "more"
}
},
{
"name": "name",
"dob": "dob"
}
],
"$meta": {
"one": 1,
"two": 2
}
}
function removeMeta(obj) {
for(prop in obj) {
if (prop === '$meta')
delete obj[prop];
else if (typeof obj[prop] === 'object')
removeMeta(obj[prop]);
}
}
removeMeta(myObj);
console.log(myObj);
As #floor commented above:
JSON.parse(JSON.stringify(obj, (k,v) => (k === '$meta')? undefined : v))
// Helper function
function removeProps(obj,keys){
if(Array.isArray(obj)){
obj.forEach(function(item){
removeProps(item,keys)
});
}
else if(typeof obj === 'object' && obj != null){
Object.getOwnPropertyNames(obj).forEach(function(key){
if(keys.indexOf(key) !== -1)delete obj[key];
else removeProps(obj[key],keys);
});
}
}
// The object we want to iterate
var obj = {
"part_one": {
"name": "My Name",
"something": "123",
"$meta": {
"test": "test123"
}
},
"part_two": [
{
"name": "name",
"dob": "dob",
"$meta": {
"something": "else",
"and": "more"
}
},
{
"name": "name",
"dob": "dob"
}
],
"$meta": {
"one": 1,
"two": 2
}
};
// Utilize the utility
removeProps(obj,['$meta']);
// Show the result
document.body.innerHTML = '<pre>' + JSON.stringify(obj,null,4) + '</pre>';
I created this functions when any key is in any level in the object using the reference function of #Joseph Marikle
const _ = require("lodash");
const isObject = obj => obj != null && obj.constructor.name === "Object";
const removeAttrDeep = (obj, key) => {
for (prop in obj) {
if (prop === key) delete obj[prop];
else if (_.isArray(obj[prop])) {
obj[prop] = obj[prop].filter(k => {
return !_.isEmpty(removeAttrDeep(k, key));
});
} else if (isObject(obj[prop])) removeAttrDeep(obj[prop], key);
}
return obj;
};
EXAMPLE:
const _obj = {
a: "b", b: "e", c: { a: "a", b: "b", c: "c"},
d: [ { a: "3" }, { b: ["2", "3"] }]};
console.log(removeAttrDeep(_obj, "b"));
(Apologies, I do not yet have enough reputation points to comment directly.)
Just FYI, typeof null === 'object', so in the removeMeta() example offered by #joseph-marikle, the function will recurse on a null value.
Read more here: why is typeof null "object"?
Here is a function that takes either a string or an array of strings to remove recursively (based on Joseph's answer):
// removes all propsToRemove (passed as an array or string), drilling down up to maxLevel times
// will modify the input and return it
du.removeAllPropsFromObj = function(obj, propsToRemove, maxLevel) {
if (typeof maxLevel !== "number") maxLevel = 10
for (var prop in obj) {
if (typeof propsToRemove === "string" && prop === propsToRemove)
delete obj[prop];
else if (propsToRemove.indexOf(prop) >= 0) // it must be an array
delete obj[prop];
else if (typeof obj[prop] === "object" && maxLevel>0)
du.removeAllPropsFromObj(obj[prop], propsToRemove, maxLevel-1);
}
return obj
}
// recursively delete a key from anywhere in the object
// will mutate the obj - no need to return it
const deletePropFromObj = (obj, deleteThisKey) => {
if (Array.isArray(obj)) {
obj.forEach(element => deletePropFromObj(element, deleteThisKey))
} else if (typeof obj === 'object') {
for (const key in obj) {
const value = obj[key]
if (key === deleteThisKey) delete obj[key]
else deletePropFromObj(value, deleteThisKey)
}
}
}
deletePropFromObj(obj, '$meta');
This should avoid any issues with circular references
const recursiveRedact = <T extends Object>(obj: T, keys: Set<string>, visitedIn?: Set<any>): T => {
if (obj == null || typeof obj !== 'object') return obj;
const visited = visitedIn ?? new Set();
visited.add(obj);
Object.entries(obj).forEach(([key, val]) => {
if (keys.has(key)) {
obj[key as keyof T] = '[redacted]' as any;
} else if (typeof val === 'object' && !visited.has(val)) {
recursiveRedact(val, keys, visited);
}
});
return obj;
};

Iterate through JSON and change arrays to strings

I have a JSON object that was returned from an XML to js function. This xml converter creates arrays for every entry even when they should be strings. I cannot modify this original function so therefore I would like to take my final json object, iterate through it, detect if a value is an array of length 1 and, if so, change that array to a string.
Original object:
var json = {
user: {
name: ["bob"],
email: ["bob#example.org"]
},
items: [{
name: ["Object 1"]
},{
name: ["Object 2"]
}]
}
Should become:
var json = {
user: {
name: "bob",
email: "bob#example.org"
},
items: [{
name: "Object 1"
},{
name: "Object 2"
}]
}
I have considered the reviver function but a) I would like to avoid going back to a string and b) I am not sure if that would even work as it will probably just feed me each array element individually.
This recursive function seems to work for this problem:
function simplify(obj) {
for (var k in obj) {
if (Object.prototype.toString.call(obj[k]) == '[object Array]' && obj[k].length == 1) {
obj[k] = obj[k][0];
}
else if (typeof obj[k] == 'object') {
obj[k] = simplify(obj[k]);
}
}
return obj;
}
simplify(json);
Demo: http://jsfiddle.net/xkz4W/
Here's a recursive way to do it:
function flattenArrays(data) {
function processItem(item) {
if (Array.isArray(item)) {
if (item.length === 1 && typeof item[0] === "string") {
data[prop] = item[0];
} else {
for (var i = 0; i < item.length; i++) {
processItem(item[i]);
}
}
} else if (typeof item === "object") {
flattenArrays(item);
}
}
for (var prop in data) {
processItem(data[prop]);
}
}
Working demo: http://jsfiddle.net/jfriend00/L5WKs/

Categories

Resources