I am trying to change the property name /attr name of my json object.I try like that but nothing will change.I need to make json object after seen the input json and convert it like outjson
function changeData(data){
var title;
for(var i = 0; i < data.length; i++){
if(data[i].hasOwnProperty("displayName")){
data[i]["label"] = data[i]["displayName"];
delete data[i]["displayName"];
}
if(data[i].hasOwnProperty("displayDetail")){
data[i]["title"] = data[i]["displayDetail"];
delete data[i]["displayDetail"];
}
if(data[i].hasOwnProperty("inputType")){
if(data[i]["inputType"]=="NUMBER"){
data[i]["type"]="number"
}else if(data[i]["inputType"]=="TEXT"){
data[i]["type"]="text"
}else if(data[i]["inputType"]=="SWTICH"){
data[i]["type"]="select"
}
delete data[i]["inputType"];
}
}
console.log(data);
}
Try this - it's possibe to remove the if selection for inputType by creating a tiny lookup table from original value to new value:
function changeData(data) {
var map = { NUMBER: "number", TEXT: "text", SWITCH: "select" };
// data is an object - use for .. in to enumerate
for (var key in data.input) {
var e = data.input[key]; // alias for efficient structure dereferencing
e.label = e.displayName;
e.title = e.displayDetail;
e.type = map[e.inputType];
delete e.displayName;
delete e.displayDetail;
delete e.inputType;
}
};
There's really no need for the hasOwnProperty test these days - only use it if you think there's any risk that someone unsafely added to Object.prototype. jQuery manages without it quite happily, other modern code should do to.
If the mapping of field names was any longer I'd consider using another mapping table with another loop to remove the hard coded copy/delete pairs.
i have a nice Recursive function for that:
usage:
// replace list
var replacedObj = replaceAttrName(sourceObject, {foo: 'foooo', bar: 'baaar'});
so in your case you can easily do:
var newObj = replaceAttrName(json, {displayDetail: 'title', displayName: 'label', inputType: 'type'});
demo: http://jsfiddle.net/h1u0kq67/15/
the function is that:
function replaceAttrName(sourceObj, replaceList, destObj) {
destObj = destObj || {};
for(var prop in sourceObj) {
if(sourceObj.hasOwnProperty(prop)) {
if(typeof sourceObj[prop] === 'object') {
if(replaceList[prop]) {
var strName = replaceList[prop];
destObj[strName] = {};
replaceAttrName(sourceObj[prop], replaceList, destObj[strName]);
} else if(!replaceList[prop]) {
destObj[prop] = {};
replaceAttrName(sourceObj[prop], replaceList, destObj[prop]);
}
} else if (typeof sourceObj[prop] != 'object') {
if(replaceList[prop]) {
var strName = replaceList[prop];
destObj[strName] = sourceObj[prop];
} else if(!replaceList[prop]) {
destObj[prop] = sourceObj[prop];
}
}
}
}
return destObj;
}
If I am getting you right, you just want substitutions:
displayDetail => title
displayName => label
inputType => type.
I came up with the follwoing:
function changeData(data){
return JSON.parse(JSON.stringify(data).replace(/displayDetail/g, "title").replace(/displayName/g, "label").replace(/inputType/g, "type"));
}
Here is the Fiddle to play with.
Edit: I forgot replacements for "NUMBER", "TEXT" and "SWITCH".
function changeData(data){
return JSON.parse(JSON.stringify(data).replace(/displayDetail/g, "title").replace(/displayName/g, "label").replace(/inputType/g, "type").replace(/TEXT/g, "text").replace(/NUMBER/g, "number").replace(/SWITCH/g, "switch"));
}
Related
I have an empty javascript array(matrix) that I created to achieve refresh of divs. I created a function to dynamically put data in it. Then I created a function to update the Array (which I have issues).
The Data populated in the Array are data attributes that I put in a JSON file.
To better undertand, here are my data attributes which i put in json file:
var currentAge = $(this).data("age");
var currentDate = $(this).data("date");
var currentFullName = $(this).data("fullname");
var currentIDPerson = $(this).data("idPerson");
var currentGender = $(this).data("gender");
Creation of the array:
var arrayData = [];
Here is the function a created to initiate and addind element to the Array :
function initMatrix(p_currentIDPerson, p_currentGender, p_currentFullName, p_currentDate, p_currentAge) {
var isFound = false;
// search if the unique index match the ID of the HTML one
for (var i = 0; i < arrayData.length; i++) {
if(arrayData[i].idPerson== p_currentIDPerson) {
isFound = true;
}
}
// If it doesn't exist we add elements
if(isFound == false) {
var tempArray = [
{
currentIDPerson: p_currentIDPerson,
currentGender: p_currentGender,
currentFullName: p_currentFullName,
currentDate: p_currentDate, currentAge: p_currentAge
}
];
arrayData.push(tempArray);
}
}
The update function here is what I tried, but it doesn't work, maybe I'm not coding it the right way. If you can help please.
function updateMatrix(p_currentIDPerson, p_currentGender, p_currentFullName, p_currentDate, p_currentAge) {
for (var i = 0; i < arguments.length; i++) {
for (var key in arguments[i]) {
arrayData[i] = arguments[i][key];
}
}
}
To understand the '$this' and elm: elm is the clickableDivs where I put click event:
(function( $ ) {
// Plugin to manage clickable divs
$.fn.infoClickable = function() {
this.each(function() {
var elm = $( this );
//Call init function
initMatrixRefresh(elm.attr("idPerson"), elm.data("gender"), elm.data("fullname"), elm.data("date"), elm.data("age"));
//call function update
updateMatrix("idTest", "Alarme", "none", "10-02-17 08:20", 10);
// Définition de l'evenement click
elm.on("click", function(){});
});
}
$('.clickableDiv').infoClickable();
}( jQuery ));
Thank you in advance
Well... I would recommend you to use an object in which each key is a person id for keeping this list, instead of an array. This way you can write cleaner code that achieves the same results but with improved performance. For example:
var myDataCollection = {};
function initMatrix(p_currentIDPerson, p_currentGender, p_currentFullName, p_currentDate, p_currentAge) {
if (!myDataCollection[p_currentIDPerson]) {
myDataCollection[p_currentIDPerson] = {
currentIDPerson: p_currentIDPerson,
currentGender: p_currentGender,
currentFullName: p_currentFullName,
currentDate: p_currentDate,
currentAge: p_currentAge
};
}
}
function updateMatrix(p_currentIDPerson, p_currentGender, p_currentFullName, p_currentDate, p_currentAge) {
if (myDataCollection[p_currentIDPerson]) {
myDataCollection[p_currentIDPerson] = {
currentGender: p_currentGender,
currentFullName: p_currentFullName,
currentDate: p_currentDate,
currentAge: p_currentAge
};
}
}
Depending on your business logic, you can remove the if statements and keep only one function that adds the object when there is no object with the specified id and updates the object when there is one.
I think the shape of the resulting matrix is different than you think. Specifically, the matrix after init looks like [ [ {id, ...} ] ]. Your update function isn't looping enough. It seems like you are trying to create a data structure for storing and updating a list of users. I would recommend a flat list or an object indexed by userID since thats your lookup.
var userStorage = {}
// add/update users
userStorage[id] = {id:u_id};
// list of users
var users = Object.keys(users);
I need to convert values from one Array variable into fields of another variable in Javascript.
My variable is
field = ["entries", "body"]
and it needs to become something like
req.body.entries.body
I tried doing something like
field.forEach(function(prop){
req.body[prop] = "...";
}
but that works only on req.body.entries and req.body.body. And I need it to go all the way to req.body.entries.body
I'm doing this to get the data from a form in a document field (named entries[body]), do some cleaning up on that data, and then pass it back to node.js as if it was the request that was originally made.
UPDATE
All I need to do is to basically
exports.sanitize = function(field){
// field = ["entry","body"];
return function(req, res, next){
val = getField(req, field); // val = "Some string with data"
val = some_process(val); // some_process is a function that cleans up the string
req.body.entry.body = val; // HOW TO TAKE entry.body from the field array???
next();
}
};
As you can see, all I want is to NOT hard code entry.body but take it from field array values that passes the name of the field for processing.
If you can think of a more elegant solution to do this, please, let me know.
Thanks!
This works:
var fields = [ "field1", "field2", "field3", "field4" ];
var obj = req.body;
fields.forEach(function(prop) {
obj[prop] = {};
obj = obj[prop];
});
You want
var obj = req.body;
for (var i=0; i<fields.length-1; i++)
obj = obj[fields[i]];
var prop = fields[i];
obj[prop] = cleanUp(obj[prop]);
This will work only if req.body.entries.body is already defined:
field = ["entries","body"];
var toeval="req.body";
field.forEach(function(prop){
toeval+="."+prop;
});
toeval+="=\"...\"";
eval(toeval);
I was able to accomplish this using recursion. Hope this helps!
var foo = {
bar: {}
};
var fields = ['foobar', 'barfoo'];
function setVar (currentVar, arr, counter) {
if (arr[counter] === undefined) {
return;
}
currentVar[arr[counter]] = {};
setVar(currentVar[arr[counter]], arr, counter + 1);
}
setVar(foo.bar, fields, 0);
Often in a response from a remote API call, I receive nested objects:
var response = {
data : {
users : [
{
name : 'Mr. White'
}
]
}
}
I want to check whether the first user's name is 'Mr. White', and would naturally want to write something like.
var existed = response.data.users[0].name === 'Mr. White'
However I cannot be sure if all the objects are present, so to avoid exceptions instead I end up writing:
var existed = response && response.data && response.data.users && response.data.users[0].name === 'Mr. White'
Is there a nicer way to do this? Another ugly option that comes to mind is:
var existed = false;
try {
var existed = response.data.users[0].name === 'Mr. White';
} catch(e) { }
In addition to vanilla javascript, I usually have underscore.js and jquery available too.
Edit:
Oops, noticed I asked a dupe of javascript test for existence of nested object key.
An interesting option based on those answers is:
var existed = (((response || {}).data || {}).users || [{}])[0].name === 'Mr. White';
You could hide this naughty try/catch block inside a function like this one :
function resolve(root, path){
try {
return (new Function(
'root', 'return root.' + path + ';'
))(root);
} catch (e) {}
}
var tree = { level1: [{ key: 'value' }] };
resolve(tree, 'level1[0].key'); // "value"
resolve(tree, 'level1[1].key'); // undefined
More on this : https://stackoverflow.com/a/18381564/1636522
I would use the try catch approach but wrap it in a function to hide the ugliness.
Instead of a try/catch, this should be done via checking whether each level in the object is defined or not.
go for
if(typeof(response)!="undefined"
&& typeof(response.data)!="undefined"
&& typeof(response.data.users)!="undefined"
&& typeof(response.data.users[0])!="undefined"
&& typeof(response.data.users[0].name)!="undefined"
) {
//executes only if response.data.users[0].name is existing
}
Here is a function which I used in one of my projects http://jsfiddle.net/JBBAJ/
var object = {
data: {
users: [
{
firstName: "White"
},
{
firstName: "Black"
}
]
}
}
var read = function(path, obj) {
var path = path.split(".");
var item = path.shift();
if(item.indexOf("]") == item.length-1) {
// array
item = item.split("[");
var arrayName = item.shift();
var arrayIndex = parseInt(item.shift().replace("]", ""));
var arr = obj[arrayName || ""];
if(arr && arr[arrayIndex]) {
return read(path.join("."), arr[arrayIndex]);
} else {
return null;
}
} else {
// object
if(obj[item]) {
if(path.length === 0) {
return obj[item];
} else {
return read(path.join("."), obj[item]);
}
} else {
return null;
}
}
}
console.log(read("data.users[0].firstName", object)); // White
console.log(read("data.users[1].firstName", object)); // Black
console.log(read("data.test.users[0]", object)); // null
The idea is to pass your path as a string along with your object. The idea was to prevent the throwing of an exception and receive just null as result of the path is wrong. The good thing is that the function works with every path and you don't need to write long if statements.
I have this JSON file: http://danish-regional-data.googlecode.com/svn/trunk/danish_regional_data.json
How do I remove all the attribues within_5_km, within_10_km, within_25_km, within_50_km, within_100_km for all postcodes?
I have read this question: Remove a JSON attribute
$(document).ready(function() {
$.getJSON("post.json", function(data) {
var pc = data.postalcodes;
for (var id in pc) {
if(pc.hasOwnProperty(id)) {
for(var attr in pc[id]) {
if(pc[id].hasOwnProperty(attr) && attr.indexOf('within_') === 0) {
delete pc[id][attr];
}
}
}
}
$("#json").html(pc);
});
});
In ES2016 you can use destructing to pick the fields you want for the subset object.
//ES6 subset of an object by specific fields
var object_private = {name: "alex", age: 25, password: 123};
var {name,age} = object_private, object_public = {name,age}
//method 2 using literals
let object_public = (({name,age})=>({name,age}))(object_private);
//use map if array of objects
users_array.map(u=>u.id)
Go to the json url you provided and open the Firebug console. Then drop in the folloing code and execute it:
var p = document.getElementsByTagName('pre');
for(i=0; i < p.length; i++) {
var data = JSON.parse(p[i].innerHTML);
var pc = data.postalcodes;
// this is the code i gave you... the previous is jsut to pull it out of the page
// in Firebug - this works for me
for (var id in pc) {
if(pc.hasOwnProperty(id)) {
for(var attr in pc[id]) {
if(pc[id].hasOwnProperty(attr) && attr.indexOf('within_') === 0) {
console.log('Deleting postalcodes.'+id+'.'+attr);
delete pc[id][attr];
}
}
}
}
}
// assume data is the complete json
var pc = data.postalcodes;
for (var id in pc) {
if(pc.hasOwnProperty(id)) {
for(var attr in pc[id]) {
if(pc[id].hasOwnProperty(attr) && attr.indexOf('within_') === 0) {
delete pc[id][attr];
}
}
}
}
JSON truncated:
var data = {"postalcodes":
{"800":{"id":"800","name":"H\u00f8je Taastrup","region_ids":["1084"],"region_names":["Hovedstaden"],"commune_ids":["169"],"commune_names":["H\u00f8je-Taastrup"],"lat":"55.66713","lng":"12.27888", "within_5_km":["800","2620","2630","2633"],"within_10_km":["800","2600","2605","2620"]},
"900":{"id":"900","name":"K\u00f8benhavn C","region_ids":["1084"],"region_names":["Hovedstaden"],"commune_ids":["101"],"commune_names":["K\u00f8benhavns"],"lat":"55.68258093401054","lng":"12.603657245635986","within_5_km":["900","999"]},
"1417":{"commune_id":"390","region_id":"1085"}}};
var pc = data.postalcodes;
for (var id in pc) {
var entry = pc[id];
for(var attr in entry) {
if(attr.indexOf('within_') === 0) {
delete entry[attr];
}
}
}
console.dir(data); // your data object has been augmented at this point
you can also use regular expression
var data = {"postalcodes":
{"800":{"id":"800","name":"H\u00f8je Taastrup","region_ids":["1084"],"region_names":["Hovedstaden"],"commune_ids":["169"],"commune_names":["H\u00f8je-Taastrup"],"lat":"55.66713","lng":"12.27888", "within_5_km":["800","2620","2630","2633"],"within_10_km":["800","2600","2605","2620"]},
"900":{"id":"900","name":"K\u00f8benhavn C","region_ids":["1084"],"region_names":["Hovedstaden"],"commune_ids":["101"],"commune_names":["K\u00f8benhavns"],"lat":"55.68258093401054","lng":"12.603657245635986","within_5_km":["900","999"]},
"1417":{"commune_id":"390","region_id":"1085"}}};
var regexp = new RegExp("^within_", "i"); // case insensitive regex matching strings starting with within_
var pc = data.postalcodes;
for (var id in pc) {
var entry = pc[id];
for(var attr in entry) {
if(regexp.test(attr)) {
delete entry[attr];
}
}
}
console.dir(data);
I have written an npm module unset which exactly does this. You specify json paths similar to the json-path module until the leaf attribute that you want to remove.
let unset = require('unset');
let object = {a: { b: [ {x: 1}, {x: [{ e: 2} ]}]}};
let newObject = unset(object, ['/a/b[*]/x']);
Multiple paths are supported in the second argument
well you can do this:
var postalcodes = YOUR JSON;
for(var code in postalcodes)
{
delete postalcodes[code].within_5_km;
.
.
.
}
you will probably want to check if the code contains your properties...
When fetching an item from a DOJO datastore, DOJO adds a great deal of extra fields to it. It also changes the way the data is structure.
I know I could manually rebuild ever item to its initial form (this would require me to make updates to both JS code everytime i change my REST object), but there certainly has to be a better way.
Perhaps a store.detach( item ) or something of the sort?
The dojo.data API is being phased out, partly because of the extra fields. You could consider using the new dojo.store API. The store api does not add the extra fields.
I have written a function that does what you are looking to do. It follows. One thing to note, my function converts child objects to the { _reference: 'id' } notation. You may want different behavior.
Util._detachItem = function(item) {
var fnIncludeProperty = function(key) {
return key !== '_0'
&& key !== '_RI'
&& key !== '_RRM'
&& key !== '_S'
&& key !== '__type'
};
var store = item._S;
var fnCreateItemReference = function(itm) {
if (store.isItem(itm)) {
return { _reference: itm.id[0] };
}
return itm;
};
var fnProcessItem = function(itm) {
var newItm = {};
for(var k in itm) {
if(fnIncludeProperty(k)) {
if (dojo.isArray(itm[k])) {
// TODO this could be a problem with arrays with a single item
if (itm[k].length == 1) {
newItm[k] = fnCreateItemReference(itm[k][0]);
} else {
var valArr = [];
dojo.forEach(itm[k], function(arrItm) {
valArr.push(fnCreateItemReference(arrItm));
});
newItm[k] = valArr;
}
} else {
newItm[k] = fnCreateItemReference(itm[k]);
}
}
}
return newItm;
};
return fnProcessItem(item);
};
NOTE: this function is modified from what I originally wrote and I did not test the above code.