In my case i need a function that remove the null and undefined key parameters from the object a function that transforms this object
Purpose
i am creating this long json object from mongo DB i am saving this and and creating XML from this for voice response
{
"say": {
"value": null
},
"play": {
"value": null
},
"dial": {
"value": "7597365803",
"options": {
"action": null,
"answerOnBridge": false,
"callerId": null,
"hangupOnStar": false,
"method": "GET",
"record": true,
"recordingStatusCallback": "false",
"recordingStatusCallbackMethod": "POST",
"recordingStatusCallbackEvent": "completed",
"recordingTrack": "both",
"ringTone": null,
"timeLimit": 14400,
"timeout": 30,
"trim": "do-not-trim",
"_id": "60cc1977c86fe21910ccbc85",
"__v": 0
}
},
"record": {
"value": null
},
"gather": {
"value": null
},
"pause": {
"value": null
},
"redirect": {
"value": null
},
"reject": {
"options": null
},
"number": {
"value": null
},
"user_id": "2",
"hangup": null,
"_id": "60cc0c416349282be4ed2f16",
"__v": 0
}
into this
{
"dial": {
"value": "7597365803",
"options": {
"action": null,
"answerOnBridge": false,
"callerId": null,
"hangupOnStar": false,
"method": "GET",
"record": true,
"recordingStatusCallback": "false",
"recordingStatusCallbackMethod": "POST",
"recordingStatusCallbackEvent": "completed",
"recordingTrack": "both",
"ringTone": null,
"timeLimit": 14400,
"timeout": 30,
"trim": "do-not-trim"
}
}
}
i created this function
function cleanObject (obj: any) {
Object.keys(obj).forEach(k =>
(obj[k] && typeof obj[k] === 'object') && this.cleanObject(obj[k]) ||
(!obj[k] && obj[k] !== undefined) && delete obj[k]
)
return obj
}
but it only solve and some problem and do not run well i tried lodash but it won't help
please help me i ma stuck
here is a solution with recursion. also, pls check see this, there are a couple of solutions with recursion are present there too.
const data = {
"say": {
"value": null
},
"play": {
"value": null
},
"dial": {
"value": "7597365803",
"options": {
"action": null,
"answerOnBridge": false,
"callerId": null,
"hangupOnStar": false,
"method": "GET",
"record": true,
"recordingStatusCallback": "false",
"recordingStatusCallbackMethod": "POST",
"recordingStatusCallbackEvent": "completed",
"recordingTrack": "both",
"ringTone": null,
"timeLimit": 14400,
"timeout": 30,
"trim": "do-not-trim",
"_id": "60cc1977c86fe21910ccbc85",
"__v": 0
}
},
"record": {
"value": null
},
"gather": {
"value": null
},
"pause": {
"value": null
},
"redirect": {
"value": null
},
"reject": {
"options": null
},
"number": {
"value": undefined
},
"user_id": "2",
"hangup": null,
"_id": "60cc0c416349282be4ed2f16",
"__v": 0
}
function removeEmpty(obj) {
const newObj = {};
Object.keys(obj).forEach(function(k) {
if (obj[k] && typeof obj[k] === "object") {
const value = removeEmpty(obj[k]);
if (Object.keys(value).length != 0) {
newObj[k] = removeEmpty(obj[k]);
}
} else if (obj[k] != null && obj[k] != undefined) {
newObj[k] = obj[k];
}
});
return newObj;
}
console.log(removeEmpty(data))
if you want to remove only those keys which has null or undefined then you can try this recursive function
const isObject = _ => _ instanceof Object && _.constructor.name == "Object"
const isEmpty = _ => isObject(_) ? !!!Object.values(_).length : false
const removeNullUndefined = (obj, level, recurse = true) => {
for (let key in obj) {
if (level) {
if ([null, undefined].indexOf(obj[key]) > -1)
delete obj[key]
else if (isObject(obj[key]))
obj[key] = removeNullUndefined(obj[key], level, false)
}
if (recurse) {
if (isEmpty(obj[key]))
delete obj[key]
--level
}
}
return obj
}
removeNullUndefined(YOUR_OBJECT, 2)
You can use lodash's _.transform() to recursively iterate a nested object, and build a new object without nil values (null or undefined), and empty objects / arrays.
const cleanObject = obj =>
_.transform(obj, (acc, v, k) => {
const val = _.isObject(v) ? cleanObject(v) : v // if current value is an object clean it
if(_.isNil(val) || _.isEmpty(val)) return // ignore null, undefined, or empty objects / arrays
acc[k] = val // assign to key
})
const data = {"say":{"value":null},"play":{"value":null},"dial":{"value":"7597365803","options":{"action":null,"answerOnBridge":false,"callerId":null,"hangupOnStar":false,"method":"GET","record":true,"recordingStatusCallback":"false","recordingStatusCallbackMethod":"POST","recordingStatusCallbackEvent":"completed","recordingTrack":"both","ringTone":null,"timeLimit":14400,"timeout":30,"trim":"do-not-trim","_id":"60cc1977c86fe21910ccbc85","__v":0}},"record":{"value":null},"gather":{"value":null},"pause":{"value":null},"redirect":{"value":null},"reject":{"options":null},"number":{},"user_id":"2","hangup":null,"_id":"60cc0c416349282be4ed2f16","__v":0}
const result = cleanObject(data)
console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min.js" integrity="sha512-WFN04846sdKMIP5LKNphMaWzU7YpMyCU245etK3g/2ARYbPK9Ub18eG+ljU96qKRCWh+quCY7yefSmlkQw1ANQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
Related
I saw many answers, but I haven't been able to modify any to my need.
Object
{
"id": "476ky1",
"custom_id": null,
"name": "Reunião com o novo Gerente de Vendas - Airton",
"text_content": null,
"description": null,
"status": {
"id": "p3203621_11svBhbO"
},
"archived": false,
"creator": {
"id": 3184709
},
"time_spent": 0,
"custom_fields": [{
"id": "36c0de9a-9243-4259-ba57-bd590ba07fe0",
"name": "Comments",
"value": "dsdsdsds"
}],
"attachments": []
}
Within custom_fields, if the property name's value is Comments, update the value property.
I've tried it like this, using this approach, for example, but it doesn't produce the expected result.
const updatedComment = [{ name: "Comments", value: "The comment is updated"}];
updateNestedObj(taskData, updatedComment)
function updateNestedObj(obj, updates) {
const updateToApply = updates.find(upd => upd.id === obj.id);
if (updateToApply) {
obj.title = updateToApply.content;
obj.note = updateToApply.note;
}
// Apply updates to any child objects
for(let k in obj) {
if (typeof(obj[k]) === 'object') {
updateNestedObj(obj[k], updates);
}
}
}
You're using the wrong property names when you search updates for updateToApply, and then when assigning the value.
When you recurse on children, you need to distinguish between arrays and ordinary objects, so you can loop over the nested arrays. You also have to skip null properties, because typeof null == 'object'.
const updatedComment = [{
name: "Comments",
value: "The comment is updated"
}];
function updateNestedObj(obj, updates) {
let updateToApply = updates.find(upd => upd.name == obj.name);
if (updateToApply) {
obj.value = updateToApply.value;
}
// Apply updates to any child objects
Object.values(obj).forEach(child => {
if (Array.isArray(child)) {
child.forEach(el => updateNestedObj(el, updates));
} else if (typeof(child) === 'object' && child != null) {
updateNestedObj(child, updates);
}
});
}
const taskData = {
"id": "476ky1",
"custom_id": null,
"name": "Reunião com o novo Gerente de Vendas - Airton",
"text_content": null,
"description": null,
"status": {
"id": "p3203621_11svBhbO"
},
"archived": false,
"creator": {
"id": 3184709
},
"time_spent": 0,
"custom_fields": [{
"id": "36c0de9a-9243-4259-ba57-bd590ba07fe0",
"name": "Comments",
"value": "dsdsdsds"
}],
"attachments": []
};
updateNestedObj(taskData, updatedComment)
console.log(taskData);
Try this:
const updatedComment = [{ name: "Comments", value: "A new comment value" }]
// you can add as many updates as you want
function update(obj, updates) {
for (const update in updates) {
for (const field in obj.custom_fields) {
if (obj.obj.custom_fields.name == update.name) {
obj.obj.custom_fields.value = update.value
}
}
}
}
update(obj, updatedComment)
I have my JSON structured like below which has the next and previous properties of an array of keys from the same structure.
{
"e6e1de44-d53b-44ae-9d52-8f6e1358f8ec": {
"course": "Semester 1",
"status": "completed",
"next": [
"d1fc647b-ad7e-4b72-9269-5559948ee61d"
],
"previous": [],
},
"d1fc647b-ad7e-4b72-9269-5559948ee61d": {
"course": "Semester 2",
"status": "completed",
"next": [
"cb00b200-cee3-4ab8-af11-abb7ea26183b",
"7b958370-d697-4536-9bff-fa564a5688ef"
],
"previous": [
"e6e1de44-d53b-44ae-9d52-8f6e1358f8ec"
],
},
"cb00b200-cee3-4ab8-af11-abb7ea26183b": {
"course": "Semester 3",
"status": "active",
"next": [
"72488692-064c-436c-93cb-8ebe2be7e168"
],
"previous": [
"d1fc647b-ad7e-4b72-9269-5559948ee61d"
],
},
"7b958370-d697-4536-9bff-fa564a5688ef": {
"course": "Semester 4",
"status": "active",
"next": [
"72488692-064c-436c-93cb-8ebe2be7e168"
],
"previous": [
"d1fc647b-ad7e-4b72-9269-5559948ee61d"
],
},
"72488692-064c-436c-93cb-8ebe2be7e168": {
"course": "Final",
"status": "not-started",
"next": [],
"previous": [
"cb00b200-cee3-4ab8-af11-abb7ea26183b",
"7b958370-d697-4536-9bff-fa564a5688ef"
],
}
}
I am trying to get the next array and the previous array recursively but it is giving me an error TypeError: Cannot read properties of undefined (reading 'recursiveFunc') I'm calling a function like this.
let nextRes = [];
recursiveFunc(courseData, 'e6e1de44-d53b-44ae-9d52-8f6e1358f8ec', nextRes, true);
let prevRes = [];
recursiveFunc(courseData, 'cb00b200-cee3-4ab8-af11-abb7ea26183b', prevRes, false);
I was wondering if the same function could be used to achieve a similar result. It is just a matter of traversing forward or backward. How can I get the id of the next data recursively?
nextRes shuld have populated ['d1fc647b-ad7e-4b72-9269-5559948ee61d', 'cb00b200-cee3-4ab8-af11-abb7ea26183b', '7b958370-d697-4536-9bff-fa564a5688ef', '72488692-064c-436c-93cb-8ebe2be7e168'] and prevRes like ['d1fc647b-ad7e-4b72-9269-5559948ee61d', 'e6e1de44-d53b-44ae-9d52-8f6e1358f8ec']
function recursiveFunc(data, parId, acc, forward) {
for (let property in data) {
if (data.hasOwnProperty(property) && typeof data[property] === 'object') {
var current = data[property];
if (forward && property == parId && typeof current.preReqStages === 'object' && data[property].next.length > 0) {
acc.push(current.next);
} else if (!forward && property == parId && typeof current.preReqStages === 'object' && data[property].previous.length > 0) {
acc.push(current.previous);
} else {
this.recursiveFunc(data, property, acc, forward)
}
}
}
}
Starting in order of your code, first you don't need to validate data.hasOwnProperty(property) if you're making a for of the properties in data.
Second, your validation of typeof current.preReqStages === 'object' should be typeof current.next === 'object' or current.previous for the next if, since you don't have a value of preReqStages.
Then, you are adding current.next to your array, meaning you're adding an array inside an array, when you only want the value, so I added a forEach and added each value.
And then the recursion should be inside the matches, because what you want to get is all the chain of courses, meaning that when you get the next one, you need to get the next one of that new property. So I made the recursion inside the forEach.
Here's the final result:
const courseData = {
"e6e1de44-d53b-44ae-9d52-8f6e1358f8ec": {
"course": "Semester 1",
"status": "completed",
"next": [
"d1fc647b-ad7e-4b72-9269-5559948ee61d"
],
"previous": [],
},
"d1fc647b-ad7e-4b72-9269-5559948ee61d": {
"course": "Semester 2",
"status": "completed",
"next": [
"cb00b200-cee3-4ab8-af11-abb7ea26183b",
"7b958370-d697-4536-9bff-fa564a5688ef"
],
"previous": [
"e6e1de44-d53b-44ae-9d52-8f6e1358f8ec"
],
},
"cb00b200-cee3-4ab8-af11-abb7ea26183b": {
"course": "Semester 3",
"status": "active",
"next": [
"72488692-064c-436c-93cb-8ebe2be7e168"
],
"previous": [
"d1fc647b-ad7e-4b72-9269-5559948ee61d"
],
},
"7b958370-d697-4536-9bff-fa564a5688ef": {
"course": "Semester 4",
"status": "active",
"next": [
"72488692-064c-436c-93cb-8ebe2be7e168"
],
"previous": [
"d1fc647b-ad7e-4b72-9269-5559948ee61d"
],
},
"72488692-064c-436c-93cb-8ebe2be7e168": {
"course": "Final",
"status": "not-started",
"next": [],
"previous": [
"cb00b200-cee3-4ab8-af11-abb7ea26183b",
"7b958370-d697-4536-9bff-fa564a5688ef"
],
}
}
function recursiveFunc(data, parId, acc, forward) {
for (let property in data) {
if (typeof data[property] === 'object') {
var current = data[property];
if (forward && property == parId && typeof current.next === 'object' && current.next.length > 0) {
current.next.forEach(n => {
if (!acc.includes(n)) {
acc.push(n)
this.recursiveFunc(data, n, acc, forward)
}
});
} else if (!forward && property == parId && typeof current.previous === 'object' && current.previous.length > 0) {
current.previous.forEach(p => {
if (!acc.includes(p)) {
acc.push(p)
this.recursiveFunc(data, p, acc, forward)
}
});
}
}
}
}
let nextRes = [];
recursiveFunc(courseData, 'e6e1de44-d53b-44ae-9d52-8f6e1358f8ec', nextRes, true);
console.log(nextRes)
let prevRes = [];
recursiveFunc(courseData, 'cb00b200-cee3-4ab8-af11-abb7ea26183b', prevRes, false);
console.log(prevRes)
I have a JSON object as follows:
x = {
"prop1": {
"description": "prop1",
"dataType": "string",
"value" : "abc"
},
"prop2": {
"sub1": {
"description": "sub1",
"dataType": "integer",
"value" : 12
},
"sub2": {
"description": "sub2",
"dataType": "integer"
}
},
"prop3": {
"input": {
"name": {
"description": "input messages",
"dataType": "boolean",
"value": false
}
},
"output": {
"description": "output messages",
"dataType": "boolean",
"value": false
}
}
}
In the above object, I wanted to remove the keys(description, dataType), also remove the key if it doesn't have any value key. the expected output for the above one is as below.
y = {
"prop1": {
"value" : "abc"
},
"prop2": {
"sub1": {
"value" : 12
}
},
"prop3": {
"input": {
"name": {
"value": false
}
},
"output": {
"value": false
}
}
}
My current solution is as follows:
function findValue(obj, string, obj1) {
if (obj.hasOwnProperty("value")) {
obj1[string.substring(1)] = obj.value
return
}
for (var key in obj) {
findValue(obj[key], [string, key].join("."), obj1)
}
}
console.log(x);
var x1 = {}
findValue(x, "", x1)
var y = {};
function assign(obj, keyPath, value) {
const lastKeyIndex = keyPath.length - 1;
for (var i = 0; i < lastKeyIndex; ++i) {
const key = keyPath[i];
if (!(key in obj)) {
obj[key] = {}
}
obj = obj[key];
}
obj[keyPath[lastKeyIndex]] = { "value": value };
}
Object.keys(x1).forEach(key => {
const keyPath = key.split('.');
let value = x1[key];
if (value != null) {
this.assign(y, keyPath, value);
}
});
console.log(y);
I did it in a very long way. I first convert my object into a format where each key is the combination of parent and child keys and then converted it into the expected format.
Is there any way to make it better?
I want to remove all the keys associated with null, I tried with _.filter, _.compact, _.reject, but nothing works for me, am using latest version of underscore 1.8.3
This is what I tried:
_.reject(Obj,function (value) {
return value===null;
})
_.compact(Obj)
Object:
var Obj = {
"pCon": [
{
"abc": null,
"def": null,
"ghi": {
"content": "abc"
}
},
{
"abc": null,
"def": {
imgURL: "test.png"
},
"ghi": null
},
{
"abc": {
"key": "001"
},
"def": null,
"ghi": null
}
]
}
A solution in plain Javascript in a recursive style.
function deleteNull(o) {
if (typeof o === 'object') {
Object.keys(o).forEach(function (k) {
if (o[k] === null) { // or undefined or '' ...?
delete o[k];
return;
}
deleteNull(o[k]);
});
}
}
var object = { "pCon": [{ "abc": null, "def": null, "ghi": { "content": "abc" } }, { "abc": null, "def": { imgURL: "test.png" }, "ghi": null }, { "abc": { "key": "001" }, "def": null, "ghi": null }] };
deleteNull(object);
document.write('<pre>' + JSON.stringify(object, 0, 4) + '</pre>');
for (var i in Obj["pCon"]) {
if (Obj["pCon"][i]["abc"] === null || Obj["pCon"][i]["abc"] === undefined) {
// test[i] === undefined is probably not very useful here
delete Obj["pCon"][i]["abc"];
}
if (Obj["pCon"][i]["def"] === null || Obj["pCon"][i]["def"] === undefined) {
// test[i] === undefined is probably not very useful here
delete Obj["pCon"][i]["def"];
}
if (Obj["pCon"][i]["ghi"] === null || Obj["pCon"][i]["ghi"] === undefined) {
// test[i] === undefined is probably not very useful here
delete Obj["pCon"][i]["ghi"];
}
}
it works in jsfiddle
https://jsfiddle.net/3wd7dmex/1/
This is the solution using underscore. Please note that this will not recursively go deeper into the structure like Nina's solution does. But you can extend this to mirror that behaviour if need be.
var obj = {
"pCon": [{
"abc": null,
"def": null,
"ghi": {
"content": "abc"
}
}, {
"abc": null,
"def": {
imgURL: "test.png"
},
"ghi": null
}, {
"abc": {
"key": "001"
},
"def": null,
"ghi": null
}]
};
var result = _.chain(obj).map(function(value, key) {
value = _.map(value, function(singleObj) {
return _.pick(singleObj, _.identity) // pick the keys where values are non empty
});
return [key, value];
}).object().value();
document.write('<pre>' + JSON.stringify(result, 0, 4) + '</pre>');
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>
I have nested JSON which is as following:
var data = [
{
"id":"4",
"name":"2nd anniversary",
"date":"2015-12-17",
"location":"Mumbai",
"story_body":"Gzjjs jdk djks jdks jdkd jx djdb djd JD djbd djdj d",
"short_link":"izWfs",
"created_at":"2015-12-11 03:49:52",
"path":[
"\/SupportData\/ImpalzB2B\/uploads\/711453354154623.jpg",
"\/SupportData\/ImpalzB2B\/uploads\/90294930451449759544217.jpg",
"\/SupportData\/ImpalzB2B\/uploads\/471453355023537.jpg",
"\/SupportData\/ImpalzB2B\/uploads\/90294930451449759544223.jpg",
"\/SupportData\/ImpalzB2B\/uploads\/90294930451449759544179.jpg"
],
"update_type":"3"
},
{
"id":"7",
"name":"#1styearAnniversary",
"date":"2016-01-20",
"location":"Mumbai",
"story_body":"Bsjsj jdkdk djdkdk dkdkf kdkf dkfj fjfj fjfkjdd djkd",
"short_link":"FHXh0",
"created_at":"2016-01-20 23:10:54",
"path":"\/SupportData\/ImpalzB2B\/uploads\/11453356652175.jpg",
"update_type":"3"
},
{
"id":"19",
"name":"Product qetyfvhchv",
"description":"Cheers Vgdhvjd hugging",
"short_link":"jPE7G",
"created_at":"2016-01-18 05:03:46",
"path":"\/SupportData\/ImpalzB2B\/uploads\/90294930451453118625255.jpg",
"update_type":"4"
},
{
"id":"20",
"name":"F frfgcgj ggvvhv",
"description":" Vdhsj fgjjchk",
"short_link":"hMn8K",
"created_at":"2016-01-18 05:04:16",
"path":"\/SupportData\/ImpalzB2B\/uploads\/90294930451453118654785.jpg",
"update_type":"4"
},
{
"id":"25",
"name":"Gshsh djdj djdkd dkkd",
"description":"Bsjjd djjd djdirj dudir",
"short_link":"dhT6l",
"created_at":"2016-01-22 05:39:31",
"path":[
"\/SupportData\/ImpalzB2B\/uploads\/11453466369930.jpg",
"\/SupportData\/ImpalzB2B\/uploads\/11453466369891.jpg",
"\/SupportData\/ImpalzB2B\/uploads\/11453466369942.jpg",
"\/SupportData\/ImpalzB2B\/uploads\/11453466369934.jpg",
"\/SupportData\/ImpalzB2B\/uploads\/11453466369939.jpg"
],
"update_type":"4"
},
{
"id":"26",
"name":"For Healthy Breakfast, head over to our new restaurant in Andheri",
"description":"Delightful upma",
"short_link":"CG0i4",
"created_at":"2016-02-04 06:58:17",
"path":"\/SupportData\/ImpalzB2B\/uploads\/11454594295456.jpg",
"update_type":"4"
},
{
"id":"1",
"body":"#Awesome2Eat",
"votes":"28",
"update_type":"7",
"short_link":"GcKAe",
"created_at":"2016-02-04 01:28:53",
"name":"nehil"
},
{
"id":"10",
"body":"#Bouncy",
"votes":"1",
"update_type":"7",
"short_link":"JXUxz",
"created_at":"2016-02-04 00:12:52",
"name":"nehil"
},
{
"id":"11",
"body":"#Superman",
"votes":"0",
"update_type":"7",
"short_link":"4Keyd",
"created_at":"2016-02-04 01:17:36",
"name":"nehil"
}
]
How do I get lenght of path array from Object?
I tried which gives wrong length.
for (var key in data) {
if(data[key].update_type == '3'){
console.log(data[key].path.length); // 5 and 49 . It Should be 5 and 1
}
};
Also Is this the right way to get each element of Object? :
for (var key in data) {
console.log(data[key].id);
$.each(data[key].path, function (i, obj) {
console.log(obj);
});
};
Fiddle link: http://jsfiddle.net/Nehil/2ym3ffo0/
Because the type of value of data[key].path is not array (second instance), it is a String. And String also has the length attribute which gives the length of string.
make it
for (var key in data) {
if(data[key].update_type == '3')
{
if (typeof data[key].path == "string" )
{
console.log( 1 );
}
else
{
console.log(data[key].path.length); // 5 and 49 . It Should be 5 and 1
//to print all the elements on the console one by one
if ( data[key].path && data[key].path.length > 0 )
{
data[key].path.forEach( function(value){
console.log( value );
} );
}
}
}
}
You can use forEach loop:
The forEach() method executes a provided function once per array
element.
var data = [{
"id": "4",
"name": "2nd anniversary",
"date": "2015-12-17",
"location": "Mumbai",
"story_body": "Gzjjs jdk djks jdks jdkd jx djdb djd JD djbd djdj d",
"short_link": "izWfs",
"created_at": "2015-12-11 03:49:52",
"path": [
"\/SupportData\/ImpalzB2B\/uploads\/711453354154623.jpg",
"\/SupportData\/ImpalzB2B\/uploads\/90294930451449759544217.jpg",
"\/SupportData\/ImpalzB2B\/uploads\/471453355023537.jpg",
"\/SupportData\/ImpalzB2B\/uploads\/90294930451449759544223.jpg",
"\/SupportData\/ImpalzB2B\/uploads\/90294930451449759544179.jpg"
],
"update_type": "3"
}, {
"id": "7",
"name": "#1styearAnniversary",
"date": "2016-01-20",
"location": "Mumbai",
"story_body": "Bsjsj jdkdk djdkdk dkdkf kdkf dkfj fjfj fjfkjdd djkd",
"short_link": "FHXh0",
"created_at": "2016-01-20 23:10:54",
"path": "\/SupportData\/ImpalzB2B\/uploads\/11453356652175.jpg",
"update_type": "3"
}, {
"id": "19",
"name": "Product qetyfvhchv",
"description": "Cheers Vgdhvjd hugging",
"short_link": "jPE7G",
"created_at": "2016-01-18 05:03:46",
"path": "\/SupportData\/ImpalzB2B\/uploads\/90294930451453118625255.jpg",
"update_type": "4"
}, {
"id": "20",
"name": "F frfgcgj ggvvhv",
"description": " Vdhsj fgjjchk",
"short_link": "hMn8K",
"created_at": "2016-01-18 05:04:16",
"path": "\/SupportData\/ImpalzB2B\/uploads\/90294930451453118654785.jpg",
"update_type": "4"
}, {
"id": "25",
"name": "Gshsh djdj djdkd dkkd",
"description": "Bsjjd djjd djdirj dudir",
"short_link": "dhT6l",
"created_at": "2016-01-22 05:39:31",
"path": [
"\/SupportData\/ImpalzB2B\/uploads\/11453466369930.jpg",
"\/SupportData\/ImpalzB2B\/uploads\/11453466369891.jpg",
"\/SupportData\/ImpalzB2B\/uploads\/11453466369942.jpg",
"\/SupportData\/ImpalzB2B\/uploads\/11453466369934.jpg",
"\/SupportData\/ImpalzB2B\/uploads\/11453466369939.jpg"
],
"update_type": "4"
}, {
"id": "26",
"name": "For Healthy Breakfast, head over to our new restaurant in Andheri",
"description": "Delightful upma",
"short_link": "CG0i4",
"created_at": "2016-02-04 06:58:17",
"path": "\/SupportData\/ImpalzB2B\/uploads\/11454594295456.jpg",
"update_type": "4"
}, {
"id": "1",
"body": "#Awesome2Eat",
"votes": "28",
"update_type": "7",
"short_link": "GcKAe",
"created_at": "2016-02-04 01:28:53",
"name": "nehil"
}, {
"id": "10",
"body": "#Bouncy",
"votes": "1",
"update_type": "7",
"short_link": "JXUxz",
"created_at": "2016-02-04 00:12:52",
"name": "nehil"
}, {
"id": "11",
"body": "#Superman",
"votes": "0",
"update_type": "7",
"short_link": "4Keyd",
"created_at": "2016-02-04 01:17:36",
"name": "nehil"
}]
data.forEach((a) => { /*ES6 Arrow funtion. can use simple 'function(){}' too*/
if (typeof a.path == "string") {
console.log(1);
} else if(typeof a.path!=='undefined') {
console.log(a.path.length);
}else{
console.log(-1);
}
})
repeatedly throughout this answer I use this code:
var path = (item.path && typeof item.path == 'string' ? [item.path] : item.path) || [];
breaking it down, if item.path is truthy, if it's a string, set it to [item.path] (i.e. an array with a single element == item.path), othewise use item.path
if this results in a falsey value (item.path is undefined or null etc) set path = [] an empty array
Now path will always be an array, so .length/.forEach/$.each will work without any issue (except if item.path is something other that string/array/undefined/null of course)
as you already use jquery.each, you could do this
$.each(data, function(i, item) {
if (item.update_type == '3') {
var path = (item.path && typeof item.path == 'string' ? [item.path] : item.path) || [];
console.log(path.length);
}
});
and
$.each(data, function(i, item) {
console.log(item.id);
var path = (item.path && typeof item.path == 'string' ? [item.path] : item.path) || [];
$.each(path, function (i, obj) {
console.log(obj);
});
});
I prefer to use jquery as little as possible
data.forEach(function (item) {
if (item.update_type == '3') {
var path = (item.path && typeof item.path == 'string' ? [item.path] : item.path) || [];
console.log(path.length);
}
});
and
data.forEach(function (item) {
console.log(item.id);
var path = (item.path && typeof item.path == 'string' ? [item.path] : item.path) || [];
path.forEach(function (obj) {
console.log(obj);
});
});
to use forEach you may need this polyfill if you think you may need to support IE8 or less
This is my solution using UnderscoreJs:
_.each(data, function(item) {
if (item['update_type'] != '3') return;
var path = (_.isString(item.path) ? [item.path] : item.path) || [];
var pathCount = path.length;
// Log path count for item.
pathCount && console.log(pathCount);
// Or log path list for item.
pathCount && _.each(path, function(pathStr) { console.log(pathStr); });
});