Swap undefined value with empty string - javascript

I have a parse method in a backbone app that builds a JSON object out of an array, however if a value is empty, it is written as undefined, which breaks the behavior of other methods, I need to set undefined values as empty strings and am having trouble doing that, any help is greatly appreciated.
Note: in this case I am trying to set the value of value: to an empty string if obj[key] = undefined
code:
parse: function(data){
return data.map(function(obj){
var key = Object.keys(obj)[0];
return {
attribute: key,
value: obj[key]
};
});
}
toQueryString: function(){
var obj = this.toQueryData(),
qs = [];
for (key in obj) {
qs.push(key + "=" + obj[key]);
}
return qs.join('&')
},
toQueryData: function(){
return this.reduce(function(memo, model){
memo[model.get('attribute')] = model.get('value');
return memo
}, {});
}

Use a ternary condition:
value: obj[key] ? obj[key] : ""
Or (as pointed out by #Derekζœ•ζœƒεŠŸε€«),
value: obj[key] || ""

You need to check if the object has the property - key.
value: obj.hasOwnProperty(key) && obj[key] != undefined ? obj[key] : ""
// or you could write it like this (which I prefer, think the bracket syntax is a little bit uglier):
value: obj.hasOwnProperty(key) && obj.key != undefined ? obj.key : ""
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/hasOwnProperty

Since your using backbone you could use underscores defaults method:
return _.defaults({attribute: key, value: obj[key]}, {value: ''});

toQueryString: function(){
var obj = this.toQueryData(),
qs = [];
for (key in obj) {
qs.push(key + "=" + (obj.hasOwnProperty(key) && obj.key != undefined ? obj.key : ""));
}
return qs.join('&')
}
This ended up being the solution, thanks Marko!

Related

For loop to check property is not undefined?

I want to make a for loop to check my class attributes, but I don't want to show those attributes what are undefined.
I have tried parse JSON with stringify and for each loop. But I've got the wrong generation.
for(var alma in Category){
if(typeof this.CatGroup !== "undefined"){
return ( "Type=" +
'"' +
this.Type
Object.keys(obj).forEach(function (key) {
if(typeof obj[key] === 'undefined'){
delete obj[key];
}
});
<C undefined/>
With this for loop, I got only undefined.
Here is one way to go about it:
const json = {
prop1: 'value1',
prop2: 'value2',
prop3: undefined,
}
console.log(
Object.entries(json)
.filter(([key, value]) => value !== undefined)
.map(([key, value]) => `${key}=${value}`)
.join(', ')
)

How to convert JSON object structure to dot notation?

I've got a variable I'm storing that will dictate what fields to exclude from a query:
excludeFields = {
Contact: {
Address: 0,
Phone: 0
}
}
I need to convert this to a dot notation that will work with Mongo's findOne, e.g.:
things.findOne({}, {fields: {'Contact.Address': 0, 'Contact.Phone': 0}})
Just passing excludeFields does not work and results in an error, "Projection values should be one of 1, 0, true, or false"
things.findOne({}, {fields: excludeFields})
Do I have to write my own function to convert from hierarchical structure to flat dot notation? Or is there some mechanism to do this in JavaScript that I'm not aware of?
This should be flexible enough for most needs:
function dotNotate(obj,target,prefix) {
target = target || {},
prefix = prefix || "";
Object.keys(obj).forEach(function(key) {
if ( typeof(obj[key]) === "object" && obj[key] !== null ) {
dotNotate(obj[key],target,prefix + key + ".");
} else {
return target[prefix + key] = obj[key];
}
});
return target;
}
Run on your excludesFields variable like so:
dotNotate(excludeFields);
It returns the current structure:
{ "Contact.Address" : 0, "Contact.Phone" : 0 }
So you can even do, inline:
things.findOne({}, {fields: dotNotate(excludeFields) })
Or provide as a projection:
var projection = { "fields": {} };
dotNotate(excludeFields,projection.fields);
things.findOne({}, projection);
Works nicely at all depths and even with arrays in an essential way, unless you need operators like $push.
I use a function pretty much similar to the accepted answer
function convertJsonToDot(obj, parent = [], keyValue = {}) {
for (let key in obj) {
let keyPath = [...parent, key];
if (obj[key]!== null && typeof obj[key] === 'object') {
Object.assign(keyValue, convertJsonToDot(obj[key], keyPath, keyValue));
} else {
keyValue[keyPath.join('.')] = obj[key];
}
}
return keyValue;
}
Here, I do an additional check 'obj[key] !== null' because unfortunately null is also of type 'object'.
I actually wanted to add this a comment to the accepted answer but couldn't because of not enough reputation.
var fields = {};
for (var k in excludeFields) {
for (var p in excludeFields[k]) {
fields[k + '.' + p] = excludeFields[k][p];
}
}
Then:
things.findOne({}, {fields: fields})

Javascript - removing undefined fields from an object [duplicate]

This question already has answers here:
Remove blank attributes from an Object in Javascript
(53 answers)
Closed 5 years ago.
Is there a clean way to remove undefined fields from an object?
i.e.
> var obj = { a: 1, b: undefined, c: 3 }
> removeUndefined(obj)
{ a: 1, c: 3 }
I came across two solutions:
_.each(query, function removeUndefined(value, key) {
if (_.isUndefined(value)) {
delete query[key];
}
});
or:
_.omit(obj, _.filter(_.keys(obj), function(key) { return _.isUndefined(obj[key]) }))
A one-liner using ES6 arrow function and ternary operator:
Object.keys(obj).forEach(key => obj[key] === undefined ? delete obj[key] : {});
Or use short-circuit evaluation instead of ternary: (#Matt Langlois, thanks for the info!)
Object.keys(obj).forEach(key => obj[key] === undefined && delete obj[key])
Same example using if statement:
Object.keys(obj).forEach(key => {
if (obj[key] === undefined) {
delete obj[key];
}
});
If you want to remove the items from nested objects as well, you can use a recursive function:
const removeEmpty = (obj) => {
let newObj = {};
Object.keys(obj).forEach((key) => {
if (obj[key] === Object(obj[key])) newObj[key] = removeEmpty(obj[key]);
else if (obj[key] !== undefined) newObj[key] = obj[key];
});
return newObj;
};
I prefer to use something like Lodash:
import { pickBy, identity } from 'lodash'
const cleanedObject = pickBy(originalObject, identity)
Note that the identity function is just x => x and its result will be false for all falsy values. So this removes undefined, "", 0, null, ...
If you only want the undefined values removed you can do this:
const cleanedObject = pickBy(originalObject, v => v !== undefined)
It gives you a new object, which is usually preferable over mutating the original object like some of the other answers suggest.
Use JSON Utilities
Overview
Given an object like:
var obj = { a: 1, b: undefined, c: 3 }
To remove undefined props in an object we can use nested JSON methods stringify and parse like so:
JSON.parse(JSON.stringify(obj))
Live Example
var obj = { a: 1, b: undefined, c: 3 }
var output = JSON.parse(JSON.stringify(obj));
console.log(output)
Limitations and warnings
Depending on how Javascript is implemented.
It is possible that undefined will be converted to null instead of just being removed.
Nested Object, Array will be converted to strings
Date, time values also converted to strings
Tested
The above code was tested in Firefox, Chrome, and Node 14.18.1 and removed "b" from all obj arrays. Still I recommend exercising caution using this method unless you are in a stable environment (such as cloud functions or docker) I would not rely on this method client side.
Because it doesn't seem to have been mentioned, here's my preferred method, sans side effects or external dependencies:
const obj = {
a: 1,
b: undefined
}
const newObject = Object.keys(obj).reduce((acc, key) => {
const _acc = acc;
if (obj[key] !== undefined) _acc[key] = obj[key];
return _acc;
}, {})
console.log(newObject)
// Object {a: 1}
This solution also avoids hasOwnProperty() as Object.keys returns an array of a given object's own enumerable properties.
Object.keys(obj).forEach(function (key) {
if(typeof obj[key] === 'undefined'){
delete obj[key];
}
});
and you can add this as null or '' for stricter cleaning.
Here's a plain javascript (no library required) solution:
function removeUndefinedProps(obj) {
for (var prop in obj) {
if (obj.hasOwnProperty(prop) && obj[prop] === undefined) {
delete obj[prop];
}
}
}
Working demo: http://jsfiddle.net/jfriend00/djj5g5fu/
Mhh.. I think #Damian asks for remove undefined field (property) from an JS object.
Then, I would simply do :
for (const i in myObj) {
if (typeof myObj[i] === 'undefined') {
delete myObj[i];
}
}
Short and efficient solution, in (vanilla) JS !
Example :
const myObj = {
a: 1,
b: undefined,
c: null,
d: 'hello world'
};
for (const i in myObj) {
if (typeof myObj[i] === 'undefined') {
delete myObj[i];
}
}
console.log(myObj);
This one is easy to remember, but might be slow. Use jQuery to copy non-null properties to an empty object. No deep copy unless you add true as first argument.
myObj = $.extend({}, myObj);
Another Javascript Solution
for(var i=0,keys = Object.keys(obj),len=keys.length;i<len;i++){
if(typeof obj[keys[i]] === 'undefined'){
delete obj[keys[i]];
}
}
No additional hasOwnProperty check is required as Object.keys does not look up the prototype chain and returns only the properties of obj.
DEMO

toString all the object datas

I have an object (json) like this in node.js:
var data = {
string : "name",
number : 123456789 ,
n : null ,
bool : false ,
bool2 : true
};
But I need to conver it to something like this:
{
string : "name",
number : "123456789" ,
n : "null" ,
bool : "false" ,
bool2 : "true"
};
I used this codes but not works.
for ( var index in data ){
data[index] = data[index].toString();
};
// or this
data.toString();
How can I fix it?
UPDATE
this data object is created as a new mongoose schema.
Your code looks fine, except for one thing: null doesn't have .toString() method. So, it's best to use String instead:
for ( var key in data ){
data[key] = String(data[key]);
};
String is a string constructor. It takes anything and produces a string representation of it.
Update
But this solution won't work for complex data structures. Though, if you need a JSON string, then you could use JSON.stringify with tricky replacer:
function replaceWithString(k, v) {
if ((typeof v === 'object') && (v !== null)) {
return v;
} else {
return String(v);
}
}
JSON.stringify(data, replaceWithString);
and if you want to make it pretty:
JSON.stringify(data, replaceWithString, 2);
N.B. As Bergi noticed in comments, you could use Object(v) === v instead of (typeof v === 'object') && (v !== null) to check that v is an object.
Update2
It looks like data in your example is a mongoose document.
The problem with mongoose is that it wraps all its object with the whole pack of nasty getters and setters to make them look like plain JS objects, which they are not.
So, if you're working with mongoose documents, you should call .toObject() or .toJSON() before trying to do anything with it:
data = doc.toObject(); // converts doc to plain JS object
Though, my second solution with JSON.stringify should work anyway, because stringify calls .toJSON() automatically.
for (var index in data) {
if (data[index] === null) {
data[index] = "null";
}
else if (data[index] === undefined) {
data[index] = "undefined";
}
else {
data[index] = data[index].toString();
}
}
Try this:
var val = null;
for(var key in data){
if(data.hasOwnProperty(key)){
val = data[key];
val = val === null ? 'null' : (val === undefined ? 'undefined' : val.toString());
data[key] = val;
}
}
It simply converts null to "null" and undefined to "undefined"
Note that values of your object must be a primitive data type for this to work. btw, this will work fine for your example.
A simple
JSON.stringify(data);
should work.
when doing
data[index].toString();
you are referencing a null on the third run. null has no such method toString().
Just thought I'd answer with a code that's a bit different:
for(var x in data){
data[x] = ""+data[x]+"";
}
Works.

Is there any way to rename js object keys using underscore.js

I need to convert a js object to another object for passing onto a server post where the names of the keys differ for example
var a = {
name : "Foo",
amount: 55,
reported : false,
...
<snip/>
...
date : "10/01/2001"
}
needs to turn into
a = {
id : "Foo",
total : 55,
updated: false,
...
<snip/>
...
issued : "10/01/2001"
}
where I have lookup obj available for mapping all the keys
var serverKeyMap = {
name : "id",
amount : "total",
reported : "updated",
...
date : "issue"
}
Is there a function available in underscore.js or jQuery that I can use that does this functionality?
thanks
I know you didn't mention lodash and the answers already solve the problem, but someone else might take advantage of an alternative.
As #CookieMonster mentioned in the comments, you can do this with _.mapKeys:
_.mapKeys(a, function(value, key) {
return serverKeyMap[key];
});
And the fiddle: http://jsfiddle.net/cwkwtgr3/
Similar to #pimvdb, you can also do it with a _.reduce:
_.reduce(a, function(result, value, key) {
key = map[key] || key;
result[key] = value;
return result;
}, {});
Fiddle: http://jsfiddle.net/T9Lnr/39/
As far as I know there is no function built into either of these two libraries. You can make your own fairly easily, though: http://jsfiddle.net/T9Lnr/1/.
var b = {};
_.each(a, function(value, key) {
key = map[key] || key;
b[key] = value;
});
You could copy the values to the new properties with standard JavaScript, and remove the original properties with omit, as follows:
a.id = a.name;
a.total = a.amount;
a.updated = a.reported;
a = _.omit(a, 'name', 'amount', 'reported');
// key_map: {old_name1: new_name1, ... }
function rename_keys(object, key_map, is_picked=false){
keys = _.keys(key_map);
new_keys = _.values(key_map);
picked = _.pick(object, keys);
renamed = _.object(new_keys, _.values(picked));
if(is_picked) return renamed;
return _.chain(object).omit(keys).extend(renamed).value();
}
This may be slower than above answers.
No there is no function in either library that explicitly renames keys. Your method is also the fastest (see jsperf tests.) Your best bet, if possible, is to refactor either the client side or server side code so the objects are the same.
I have a transformation operator and would just like to apply it to all keys. I forked pimvdb's fiddle to produce a simple example. In this case it Capitalizes the key. And it dynamically builds the keymap, which I needed to assure works (thanks JSFiddle).
Here is the changed code:
var keymap = {};
_.each(a, function(value, key) {
var oldkey = key;
key = capitalize(key);
keymap[oldkey] = key;
});
_.each(a, function(value, key) {
key = keymap[key] || key;
b[key] = value;
});
Fiddle:
http://jsfiddle.net/mr23/VdNjf/
It's been solved here https://stackoverflow.com/a/30940370/1360897
var keyMapping = {'PropertyA': 'propertyA', ..., 'PropertyF': 'propertyNEW'}
and also a mapping of old and new values, like this
var valueMapping = {'Y': true, 'F': false}
And then using _.map and _.transform, you can transform the object, like this
var result = _.map(allItems, function(currentObject) {
return _.transform(currentObject, function(result, value, key) {
if (key === 'PropertyF' || key === 'PropertyG') {
value = valueMapping(value);
}
result[keyMapping[key]] = value;
});
});
Why don't you use this simple java script ? Value of any key:value pair should be string/number/Boolean.
<script type="text/javascript">
var serverKeyMap = {
name : "id",
amount : "total",
reported : "updated"
};
var a = {
name : "Foo",
amount: 55,
reported : false
};
var b={}; // b is object where you will get your output
for(i in serverKeyMap) b[serverKeyMap[i]]=a[i];
console.log(b); // It gives what you need.
</script>
As user2387823 was saying above πŸ‘† using omit is a great option. For example you could write something like this
function updateObjKey(obj, currentKey, newKey) {
var keyValue = obj[currentKey];
obj = _.omit(obj, [currentKey]);
obj[newKey] = keyValue;
return obj;
}
this ES2015/2017 version πŸ§™β€β™‚οΈ
function objectMap(source,keyMap) {
return Object.entries(keyMap).reduce((o,[key , newKey]) => {
o[newKey]=source[key]
return o;},{})
}
const obj = {
name : "Foo",
amount: 55,
reported : false,
date : "10/01/2001"
}
const serverKeyMap = {
name : "id",
amount : "total",
reported : "updated",
date : "issue"
}
const result = objectMap(obj,serverKeyMap);
console.log('🎬 =>' , result);
[Object.entries][1] is es2017 feture will return object key and
value as array
[["name", "id"],["amount", "total"],...]
You really don't need underscore/lodash for this ... nowadays anyways (I realize the question was asked 9 years ago, but this question is (still) ranked highly in search results and I came across it today :-) )
Here's another plain ES2015/2017 version that I like, inspired by #malbarmavi's answer (there's probably a bunch of other plain JS functions out there, but I didn't come across any others in my brief search):
// A general key transform method. Pass it a function that accepts the old key and returns
// the new key.
//
// #example
// obj = transformKeys(obj, (key) => (
// key.replace(/\b(big)\b/g, 'little')
// ))
export function transformKeys(source, f) {
return Object.entries(source).reduce((o, [key, value]) => {
o[f(key) || key] = value
return o
}, {})
}
// Provide an object that maps from old key to new key
export function rekeyObject(source, keyMap) {
transformKeys(source, key => keyMap[key])
}
I referred the lodash documentation ans found mapKeys
https://lodash.com/docs/4.17.15#mapKeys
_.mapKeys({ 'a': 1, 'b': 2 }, function(value, key) {
return key + value;
});
// => { 'a1': 1, 'b2': 2 }
this perfectly renames the keys and return an object containing the modified desirable object
Using underscore omit and spread operator.
a = _.omit({
...a,
id: a.name,
total: a.amount,
updated: a.reported,
}, ['name', 'amount', 'reported']);
Key assignments below spread operator loads new keys and omit omits the old ones.
You can create your new custom function :
lodash.rename = function(obj, keys, newKeys) {
keys.map((key, index) => {
if(lodash.includes(lodash.keys(obj), key)) {
obj[newKeys[index]] = lodash.clone(obj[key], true);
delete obj[key];
}
});
return obj;
};
Or else if you want to edit only one keyName:
lodash.rename = function(obj, key, newKey) {
if(lodash.includes(lodash.keys(obj), key)) {
obj[newKeys[index]] = lodash.clone(obj[key], true);
delete obj[key];
}
return obj;
};
Using lodash
var obj = _.renameKeys( { 1 : "Geeks",
2 : "Computer_Science_Portal" },
{ 1 : "g", 2 : "c" });
so in your case, you want to apply the serverKeyMap onto object a :
var obj = _.renameKeys(a, serverKeyMap);
from https://www.geeksforgeeks.org/lodash-_-renamekeys-method/

Categories

Resources