find null values in multidimensional associative array - javascript

Is there a way to search through an associative array with an unknown number of dimensions and change all the null values to an empty string?
Thanks!

Something like this maybe:
var objectNullToEmpty = function (obj) {
for (key in obj) {
if (obj[key] === null) {
obj[key] = '';
}
if (typeof obj[key] === 'object') {
objectNullToEmpty(obj[key]);
}
}
return obj;
};

Related

Converting object and/or nested array with objects to valid JSON string representation without using JSON.stringify?

I'm having trouble outputting a valid JSON string from an object as input without using JSON.stringify().
Here is my current complete implementation -
var my_json_encode = function(input) {
if(typeof(input) === "string"){
return '"'+input+'"'
}
if(typeof(input) === "number"){
return `${input}`
}
if(Array.isArray(input)) {
const formatedArrayMembers = input.map(value => my_json_encode(value)).join(',');
return `[${formatedArrayMembers}]`;
}
*****Trouble is here*******
if(typeof(input) === "object" && !Array.isArray(input)) {
let temp = "";
for (let [key, value] of Object.entries(input)) {
let val = `${key} : ${value}`;
temp += my_json_encode(val)
}
return `{${temp}}`
}
}
Current input is -> {"key1":"val1","key2":"val2"}
Expected output is -> {"key1":"val1","key2":"val2"}
Current output using object type check in my_json_encode -> {"key1 : val1""key2 : val2"}
I feel that I'm close but something is missing in my logic, I've started at this for to long and need some guidance.
If I can get my object encoder to work, I'm sure I can recursively use it to check more complicated inputs such as:
Expected Output-> [1,"a",{"key1":"value1","key2":null,"key3":[4,"b"],"key5":{"inner1":"innerval1","inner2":9}}]
Related question I asked for an array to JSON string was solved here
The main issue is that you need to put "s around the whole key when iterating over the entries, and call my_json_encode on the value:
"${key}: ${my_json_encode(value)}"
You also need each key-value pair like above to be joined by ,, which can be done easily by mapping each key-value pair to the above sort of string, then .join(',')ing them.
You should also be escaping any "s in the keys or string values with a backslash. Also note that typeof is an operator, not a function - you can use it like typeof someVar:
var my_json_encode = function(input) {
if (typeof input === "string") {
return '"' + input.replace(/"/g, '\\"') + '"'
}
if (typeof input === "number") {
return input;
}
if (Array.isArray(input)) {
const formatedArrayMembers = input.map(my_json_encode).join(',');
return `[${formatedArrayMembers}]`;
}
if (input === null) return 'null';
// then it's a non-array object
const keyValStrArray = Object.entries(input).map(([key, val]) => (
`"${key.replace(/"/g, '\\"')}":${my_json_encode(val)}`
));
return `{${keyValStrArray.join(',')}}`
};
console.log(my_json_encode({ "key1": "val1", "key2": "val2" }));
console.log(my_json_encode([1,"a",{"key1":"value1","key2":null,"key3":[4,"b"],"key5":{"inner1":"innerval1","inner2":9}}]));
For objects, you can make temp an array and just push key: my_json_encode(value) pairs to it, then joining them with , and outputting { and } around the result:
var my_json_encode = function(input) {
if (input === null) {
return "null";
}
if (typeof(input) === "string") {
return `"${input}"`;
}
if (typeof(input) === "number") {
return `${input}`;
}
if (Array.isArray(input)) {
const formatedArrayMembers = input.map(value => my_json_encode(value)).join(',');
return `[${formatedArrayMembers}]`;
}
if (typeof(input) === "object") {
let temp = [];
for (let [key, value] of Object.entries(input)) {
temp.push(`"${key}" : ${my_json_encode(value)}`);
}
return `{${temp.join(', ')}}`;
}
}
console.log(my_json_encode({key1:"val1",key2:3}));
console.log(my_json_encode([1,"a",{"key1":"value1","key2":null,"key3":[4,"b"],"key5":{"inner1":"innerval1","inner2":9}}]));

Extract key value pairs from json object and group them - Javascript

Here is my fiddle : DEMO1
The following function extracts the keys and values and stores it in a new array. This works right for objects(json2 and json3) and not when there is an array of objects (json1)
Is there a way to group a set of key value pairs into an object and then push that object into the array?
Desired output : [{"timestamp":1540457640,"speed":"70"},{"timestamp":1541383353,"speed":"80"},{"timestamp":1541383353,"speed":"70"},{"timestamp":1542256083,"speed":"70"}]
function iterate(obj) {
for (var property in obj) {
if (obj.hasOwnProperty(property)) {
if (typeof obj[property] == "object") {
iterate(obj[property]);
if (isNaN(Number(property))) {
if ((Array.isArray(obj[property])) && (typeof obj[property][0] != "object")) {
simpleArrayKeys[property] = obj[property];
}
}
} else {
if (isNaN(Number(property))) {
simpleArrayKeys[property] = obj[property];
}
}
}
}
}
You can map the data array like so:
var output = json1.data.allStreamingData.map(d => {
return {
"timestamp": d.timestamp,
"speed": d.streamData.speed
}
})
http://jsfiddle.net/fghjtsnm/

How can I filter an object of all properties that are objects?

I'm trying to make a copy of an object that only includes the properties that are not objects. But the child objects get copied along with it.
var testObject = {
stringProperty: "hi",
intProperty: 4,
objectProperty: {},
nullProperty: null
};
console.log(removeChildObjects(testObject));
function removeChildObjects(object) {
var keys = Object.keys(object);
var newObject = {};
keys.forEach(function(key) {
console.log(key, object[key], typeof object[key]);
if (typeof object[key] != "object") {
newObject[key] = object[key];
}
});
return object;
}
Also check it out here https://jsfiddle.net/uss94sc3/1/
If you want to strictly filter out object properties (keeping null and undefined properties), then you cannot rely on the broken typeof unary operator.
typeof null
// "object"
You can either change your code to:
function removeChildObjects(object) {
var keys = Object.keys(object);
var newObject = {};
keys.forEach(function(key) {
if (typeof object[key] != "object" || object[key] == null) {
newObject[key] = object[key];
}
});
return newObject;
}
or more succinctly with underscore:
function removeChildObjects(object) {
return _.omit(object, _.isObject);
}
You return the same object that passed:
return object;
You should return newObject
return newObject;
Try replacing return object; with return newObject;. It will work a lot better!
https://jsfiddle.net/w3urvpjq/
You may try this
var testObject = {
stringProperty: "hi",
intProperty: 4,
objectProperty: {},
nullProperty: null
};
var filterPrimitive = o => Object.keys(o).reduce((p,k) => {typeof o[k] != "object" && (p[k] = o[k]); return p},{});
document.write("<pre>" + JSON.stringify(filterPrimitive(testObject),null,2) + "</pre>");

Dig till deepest .value or .content

I am trying to write a function that digs an object till it gets to the last .value or .content property. I wrote this and for the life of me I cant figure out why it breaks.
var jscGetDeepest = function(obj) {
try {
console.info(Math.round(Math.random() * 10) + ' starting jscGetDeepest:', obj, obj.toString());
} catch(ignore) {}
while (obj && ('contents' in obj || 'value' in obj)) {
if ('contents' in obj) {
obj = obj.contents;
} else if ('value' in obj) {
obj = obj.value;
}
//console.info('loop jscGetDeepest:', obj.toString());
}
if (obj || obj === 0) {
obj = obj.toString();
}
console.info('finaled jscGetDeepest:', obj);
return obj;
}
The issue occurs when inner value in the next iteration is not an object. In this case you get an error message, because in operand can't be used with primitives.
To fix it check for object before trying to get deeper. Here is a fixed an slightly improved version with JSON.stringify instead of toString (maybe better to return object itself without stringifying it?):
var jscGetDeepest = function (obj) {
while (typeof obj === 'object' && obj !== null && ('contents' in obj || 'value' in obj)) {
if ('contents' in obj) {
obj = obj.contents;
} else if ('value' in obj) {
obj = obj.value;
}
}
if (typeof obj === 'object') {
obj = JSON.stringify(obj);
}
return obj;
}
alert( jscGetDeepest({value: {name: 2, contents: {name: 3, value: 23}}}) );
alert( jscGetDeepest({value: {name: 2, value: {name: 3, contents: {name: 4}}}}) );

Removing the duplicate keys of a JSON array and getting its JSON path

I have the JSON below:
{"response":{"result":{"Leads":{"row":[{"LEADID":"849730000000063017","SMOWNERID":"849730000000061001"},{"LEADID":"849730000000063015","SMOWNERID":"849730000000061001","HIII":"hello"},{"LEADID":"849730000000063007","SMOWNERID":"849730000000061001","BYEE":"tata"},{"LEADID":"849730000000063005","SMOWNERID":"849730000000061001"},{"LEADID":"849730000000063003","SMOWNERID":"849730000000061001"},{"LEADID":"849730000000063001","SMOWNERID":"849730000000061001"}]}},"uri":"/crm/private/json/Leads/getMyRecords"}}
I have the requirement to get the JSON path, for which I used the code below:
var str={"response":{"result":{"Leads":{"row":[{"LEADID":"849730000000063017","SMOWNERID":"849730000000061001",},
{"LEADID":"849730000000063015","SMOWNERID":"849730000000061001"},
{"LEADID":"849730000000063007","SMOWNERID":"849730000000061001","HIII":"hello"},
{"LEADID":"849730000000063005","SMOWNERID":"849730000000061001","BYEE":"tata"},
{"LEADID":"849730000000063003","SMOWNERID":"849730000000061001"},
{"LEADID":"849730000000063001","SMOWNERID":"849730000000061001"}]}},
"uri":"/crm/private/json/Leads/getMyRecords"}}
var keys = [];
getKeys(keys,str, '');
for(var i=0; i<keys.length; i++) {
var d=new Array();
d=keys[i][1].replace(/^\.|\.$/g, '')
console.log(keys[i][0] + '=' +d)
}
function getKeys(keys, obj, path) {
for(key in obj) {
var currpath = path+'.'+key;
keys.push([key, currpath]);
if(typeof(obj[key]) === 'object') {
getKeys(keys, obj[key], currpath);
}
}
}
Below is the output:
response=response
result=response.result
Leads=response.result.Leads
row=response.result.Leads.row
0=response.result.Leads.row.0
LEADID=response.result.Leads.row.0.LEADID
SMOWNERID=response.result.Leads.row.0.SMOWNERID
1=response.result.Leads.row.1
LEADID=response.result.Leads.row.1.LEADID
SMOWNERID=response.result.Leads.row.1.SMOWNERID
HIII=response.result.Leads.row.1.HIII
2=response.result.Leads.row.2
LEADID=response.result.Leads.row.2.LEADID
SMOWNERID=response.result.Leads.row.2.SMOWNERID
BYEE=response.result.Leads.row.2.BYEE
3=response.result.Leads.row.3
LEADID=response.result.Leads.row.3.LEADID
SMOWNERID=response.result.Leads.row.3.SMOWNERID
4=response.result.Leads.row.4
LEADID=response.result.Leads.row.4.LEADID
SMOWNERID=response.result.Leads.row.4.SMOWNERID
5=response.result.Leads.row.5
LEADID=response.result.Leads.row.5.LEADID
SMOWNERID=response.result.Leads.row.5.SMOWNERID
uri=response.uri
The array elements keys are repetitive (ie) LEADID and SMOWNERID are repetitive in the array. I want to remove the duplicates of the entire array and display the output like this:
response=response
result=response.result
Leads=response.result.Leads
row=response.result.Leads.row
0=response.result.Leads.row.0
LEADID=response.result.Leads.row.0.LEADID
SMOWNERID=response.result.Leads.row.0.SMOWNERID
HIII=response.result.Leads.row.0.HIII
BYEE=response.result.Leads.row.0.BYEE
uri=response.uri
I am stuck here, any help regarding this will be very helpful.
Modify the function getKeys to this :
function getKeys(keys, obj, path) {
for(key in obj) {
var currpath = path+'.'+key;
keys.push([key, currpath]);
if(typeof(obj[key]) === 'object') {
if(obj[key] instanceof Array){ //added check for array
keys.push(['0', currpath+'.0']);
getKeys(keys, obj[key][0], currpath+'.0');
}
else
getKeys(keys, obj[key], currpath);
}
}
}
Update
function getKeys(keys, obj, path) {
for(key in obj) {
var currpath = path+'.'+key;
addKeys(key, currpath);
//keys.push([key, currpath]);
if(typeof(obj[key]) === 'object') {
getKeys(keys, obj[key], currpath);
}
}
}
function addKeys(key, currpath) { //check before adding
present = keys.map(function(x){return(x[1].split('.').slice(-1)[0])});
if (present.indexOf(key)==-1){
keys.push([key, currpath]);
}
}
The answer is not exactly like you want but is the closest I could get. Also the values you have given for HIII and BYEE are wrong. Lastly it is possible to have same keys at different levels, but I am only matching the name of key. It may not work if same keyname is used at different levels.
Another approach is to change the keys to object from array - change the var keys = [] to var keys = {} and then change the getKeys method as follow:
function getKeys(keys, obj, path) {
for(key in obj) {
var currpath = path+'.'+key;
if(keys[key])
continue;
keys[key] = currpath;
if(typeof(obj[key]) === 'object') {
getKeys(keys, obj[key], currpath);
}
}
}
Now you will also need to change the way you print the values after the return from getKeys since now keys is not an array rather an object.

Categories

Resources