Need to change JSON property using a variable - javascript

c.key = "test";
a = {};
a.body = {};
a.body.interval={};
a.body.interval = c.key;
b = {};
b.body = {};
b.body.interval={};
b.body.interval = c.key;
c["key"]="sample";
return JSON.stringify(a);
I want to change all the values which are referred by mentioned variable in javascript.
Currently, this print
{"body":{"interval":"test"}}
I want to change properties referred by c.key.
I can not change individual properties of JSON as those are not fixed.
How can I change all the properties referred by an individual variable in javascript?

Not sure if this is exactly what you want but using a function instead of a variable can solve your problem. (since you can pass a replace function to stringify.
take a look at the following code:
c = {};
c.key = "test"
a = {};
a.body = {};
a.body.interval = function(){return c.key};
c["key"]="sample";
JSON.stringify(a, function (key, value) {
if (key == 'interval') {
return value();
} else {
return value;
}
});
c = {};
c.key = "test"
a = {};
a.body = {};
a.body.interval = function(){return c.key};
c["key"]="sample";
out = JSON.stringify(a, function (key, value) {
if (key == 'interval') {
return value();
} else {
return value;
}
});
console.log(out);

Related

Merge two custom javascript functions

This is the first function:
jQuery.fn.serializeObject = function(){
var self = this,
json = {},
push_counters = {},
patterns = {
"validate": /^[a-zA-Z][a-zA-Z0-9_]*(?:\[(?:\d*|[a-zA-Z0-9_]+)\])*$/,
"key": /[a-zA-Z0-9_]+|(?=\[\])/g,
"push": /^$/,
"fixed": /^\d+$/,
"named": /^[a-zA-Z0-9_]+$/
};
this.build = function(base, key, value){
base[key] = value;
return base;
};
this.push_counter = function(key){
if(push_counters[key] === undefined){
push_counters[key] = 0;
}
return push_counters[key]++;
};
jQuery.each(jQuery(this).serializeArray(), function(){
// skip invalid keys
if(!patterns.validate.test(this.name)){
return;
}
var k,
keys = this.name.match(patterns.key),
merge = this.value,
reverse_key = this.name;
while((k = keys.pop()) !== undefined){
// adjust reverse_key
reverse_key = reverse_key.replace(new RegExp("\\[" + k + "\\]$"), '');
// push
if(k.match(patterns.push)){
merge = self.build([], self.push_counter(reverse_key), merge);
}
// fixed
else if(k.match(patterns.fixed)){
merge = self.build([], k, merge);
}
// named
else if(k.match(patterns.named)){
merge = self.build({}, k, merge);
}
}
json = jQuery.extend(true, json, merge);
});
return json;
};
This function to serialize the form's values but the problem of this function that it's not getting the value of the unchecked inputs because that I make this function:
jQuery.fn.mySerialize = function() {
var $container = jQuery(this),
$checkboxes = $container.find("input[type='checkbox']").each(function() {
jQuery(this).val(this.checked ? 1 : 0).prop('checked', true);
});
var serialized = ($container.serializeObject());
$checkboxes.each(function() {
jQuery(this).prop('checked', jQuery(this).val() == 1);
});
return serialized;
};
And it's working as I need by directly using mySerialize function now I want to merge the edits that I make at mySerialize function to the serializeObject function because I failed to do that directly into serializeObject function because that I created the mySerialize function.
Thanks in advance and really hope anyone helps me on this.

Create a JavaScript object from string

I'm trying to create a JavaScript function that creates an object using strings for structure and fills it from DOM data.
For example, the following strings could look like this:
some.example.here = "hello"
some.example.there = "hi"
other.example = "heyo"
Which should create this object:
{
some: {
example: {
here: "hello",
there: "hi"
},
other: {
example: "heyo
}
}
The data as said comes from DOM and is being load at the code segment labeled "read data into object". The data loads fine and the object structure is being setup fine as well, but the data is not being put into the data field.
Here's the code for the function:
function getDataFromElement(element) {
obj = {};
$(element)
.find("[data-value]")
.each(function() {
// create object node
valueObj = {};
currentValueObj = valueObj;
$.each($(this).attr("data-value").split("."), function(i, objpath) {
currentValueObj[objpath] = {};
currentValueObj = currentValueObj[objpath];
});
// read data into object
if($(this).is("[data-putvalue]") && $(this).attr("data-putvalue") != "html") {
currentValueObj = $(this).attr($(this).attr("data-putvalue"));
} else {
currentValueObj = $(this).html();
}
console.log(currentValueObj);
// combine with previous gathered data
obj = $.extend(true, {}, obj, valueObj);
});
return obj;
}
Does anyone know what to do?
I would do it like this:
var createObject = function(model, name, value) {
var nameParts = name.split("."),
currentObject = model;
for (var i in nameParts) {
var part = nameParts[i];
if (i == nameParts.length-1) {
currentObject[part] = value;
break;
}
if (typeof currentObject[part] == "undefined") {
currentObject[part] = {};
}
currentObject = currentObject[part];
}
};
And then use it like that:
var model = {};
createObject(model, "some.example.here", "hello");
createObject(model, "some.example.there", "hi");
createObject(model, "other.example", "heyo");
Probably this can suit you (adapted from another project of mine, adapt and use as needed):
NOTE the element's name is taken as key and value as the value
function fields2model( $elements, dataModel )
{
$elements.each(function( ){
var $el = $(this),
name = $el.attr('name'),
key, k, i, o, val
;
key = name;
val = $el.val() || '';
k = key.split('.'); o = dataModel;
while ( k.length )
{
i = k.shift( );
if ( k.length )
{
if ( !o.hasOwnProperty( i ) ) o[ i ] = /^\d+$/.test( k[0] ) ? [ ] : { };
o = o[ i ];
}
else
{
o[ i ] = val;
}
}
});
}
Example use:
<input name="some.example.here" value="hello" />
<input name="some.example.there" value="hi" />
var model = {};
fields2model($('input,textarea,select'), model);
The example elements above will give the below model:
model = {
some: {
example: {
here: "hello",
there: "hi"
}
};
Some functional implementation:
const value = 'hello';
'some.example.here'.split('.').reverse().reduce((reduction, segment, index) => {
const result = {};
if (index === 0) {
result[segment] = value;
} else {
result[segment] = reduction;
}
return result;
}, {})
#theFreedomBanana +1
Works for me
const magicFunction = (string, value) =>
string
.split('.')
.reverse()
.reduce((acc, cur, index) => ({ [cur]: index === 0 ? value : acc }), {});

What is wrong with my observable pattern?

I'm testing the observable pattern in javascript. My callbacks in the array never seem to execute. What is wrong with my syntax?
<script type="text/javascript">
var Book = function (value) {
var onChanging = [];
this.name = function () {
for (var i = 0; i < onChanging.length; i++) {
onChanging[i]();
}
return value;
}
this.addTest = function (fn) {
onChanging.push(fn);
}
}
var b = new Book(13);
b.addTest(function () { console.log("executing"); return true; });
b.name = 15;
</script>
From your code above it looks like you need to call your function name instead of assigning a value something like:
var b = new Book(13);
b.addTest(function () { console.log("executing"); return true; });
b.name(); //<-- Before b.name = 15
Setting b.name = 15 doesn't execute the function, it just overwrites the value of b.name.
You could use getters and setters to react to a changing value. See John Resig's blog post or the MDN reference
I edited your code to use them:
var Book = function (value) {
this.onChanging = [];
this._name = "";
}
Book.prototype = {
addTest: function (fn) {
this.onChanging.push(fn);
},
get name() {
return this._name;
},
set name(val) {
for (var i = 0; i < this.onChanging.length; i++) {
this.onChanging[i](val);
}
this._name = val;
}
};
var b = new Book(13);
b.addTest(function (val) {
console.log("executing", val);
return true;
});
b.name = 15;
b.name = 17;
working demo.
You can also make a more generic solution that can work for all your properties without having to define the getters and setters, a lot of frameworks use this approach.
Book = function () {
this._events = [];
this._rawdata = {};
}
Book.prototype = {
bind: function (fn) {
this._events.push(fn);
},
// pass the property, and it returns its value, pass the value and it sets it!
attr: function (property, val) {
if (typeof val === "undefined") return this._rawdata[property];
this._rawdata[property] = val;
for (var i = 0; i < this._events.length; i++)
// we pass out the val and the property
this._events[i](val, property);
}
};
b = new Book();
b.bind(function (val) {
console.log("executing", val);
return true;
});
b.attr("name","The Hobbit");
b.attr("SKU" ,1700109393901);
console.log(b.attr("name")); // --> The Hobbit
http://jsfiddle.net/wv4ch6as/
Of course you would want to change the binder so that you can bind onto properties not one bind for all properties, but I think this gets the idea.

Build object in JavaScript from PHP form input name

There are a couple of similar questions but none covers the case when a string looks like some-name[][some-key]. I have tried JSON.parse('some-name[][some-key]'); but it doesn't parse it.
Is there a way to convert such string to a JavaScript object that will look like { 'some-name': { 0: { 'some-key': '' } } }?
This is a name of a form field. It's normally parsed by PHP but I'd like to parse it with JavaScript the same way. I basically have <input name="some-name[][some-key]"> and I'd like to convert that to var something = { 'some-name': { 0: { 'some-key': VALUE-OF-THIS-FIELD } } }.
Try this:
JSON.parse('{ "some-name": [ { "some-key": "" } ] }');
I don't know exactly how you're doing this, but assuming they are all that format (name[][key]) and you need to do them one by one - this works for me:
var fieldObj = {};
function parseFieldName(nameStr)
{
var parts = nameStr.match(/[^[\]]+/g);
var name = parts[0];
var key = typeof parts[parts.length-1] != 'undefined' ? parts[parts.length-1] : false;
if(key===false) return false;
else
{
if(!fieldObj.hasOwnProperty(name)) fieldObj[name] = [];
var o = {};
o[key] = 'val';
fieldObj[name].push(o);
}
}
parseFieldName('some-name[][some-key]');
parseFieldName('some-name[][some-key2]');
parseFieldName('some-name2[][some-key]');
console.log(fieldObj); //Firebug shows: Object { some-name=[2], some-name2=[1]} -- stringified: {"some-name":[{"some-key":"val"},{"some-key2":"val"}],"some-name2":[{"some-key":"val"}]}
o[key] = 'val'; could of course be changed to o[key] = $("[name="+nameStr+"]").val() or however you want to deal with it.
Try this:
var input = …,
something = {};
var names = input.name.match(/^[^[\]]*|[^[\]]*(?=\])/g);
for (var o=something, i=0; i<names.length-1; i++) {
if (names[i])
o = o[names[i]] || (o[names[i]] = names[i+1] ? {} : []);
else
o.push(o = names[i+1] ? {} : []);
}
if (names[i])
o[names[i]] = input.value;
else
o.push(input.value);
Edit: according to your updated example, you can make something like this (view below). This will work - but only with the current example.
var convertor = function(element) {
var elementName = element.getAttribute('name');
var inpIndex = elementName.substring(0, elementName.indexOf('[')),
keyIndex = elementName.substring(elementName.lastIndexOf('[') + 1, elementName.lastIndexOf(']'));
var strToObj = "var x = {'" + inpIndex + "': [{'" + keyIndex + "': '" + element.value + "'}]}";
eval(strToObj);
return x;
};
var myObject = convertor(document.getElementById('yourInputID'));
Example here: http://paulrad.com/stackoverflow/string-to-array-object.html
(result is visible in the console.log)
old response
Use eval.. but your string must have a valid javascript syntax
So:
var str = "arr[][123] = 'toto'";
eval(str);
console.log(arr);
Will return a syntax error
Valid syntax will be:
var str = "var arr = []; arr[123] = 'toto'";
var x = eval(str);
console.log(arr);

Serialize JavaScript object into JSON string

I have this JavaScript prototype:
Utils.MyClass1 = function(id, member) {
this.id = id;
this.member = member;
}
and I create a new object:
var myobject = new MyClass1("5678999", "text");
If I do:
console.log(JSON.stringify(myobject));
the result is:
{"id":"5678999", "member":"text"}
but I need for the type of the objects to be included in the JSON string, like this:
"MyClass1": { "id":"5678999", "member":"text"}
Is there a fast way to do this using a framework or something? Or do I need to implement a toJson() method in the class and do it manually?
var myobject = new MyClass1("5678999", "text");
var dto = { MyClass1: myobject };
console.log(JSON.stringify(dto));
EDIT:
JSON.stringify will stringify all 'properties' of your class. If you want to persist only some of them, you can specify them individually like this:
var dto = { MyClass1: {
property1: myobject.property1,
property2: myobject.property2
}};
It's just JSON? You can stringify() JSON:
var obj = {
cons: [[String, 'some', 'somemore']],
func: function(param, param2){
param2.some = 'bla';
}
};
var text = JSON.stringify(obj);
And parse back to JSON again with parse():
var myVar = JSON.parse(text);
If you have functions in the object, use this to serialize:
function objToString(obj, ndeep) {
switch(typeof obj){
case "string": return '"'+obj+'"';
case "function": return obj.name || obj.toString();
case "object":
var indent = Array(ndeep||1).join('\t'), isArray = Array.isArray(obj);
return ('{['[+isArray] + Object.keys(obj).map(function(key){
return '\n\t' + indent +(isArray?'': key + ': ' )+ objToString(obj[key], (ndeep||1)+1);
}).join(',') + '\n' + indent + '}]'[+isArray]).replace(/[\s\t\n]+(?=(?:[^\'"]*[\'"][^\'"]*[\'"])*[^\'"]*$)/g,'');
default: return obj.toString();
}
}
Examples:
Serialize:
var text = objToString(obj); //To Serialize Object
Result:
"{cons:[[String,"some","somemore"]],func:function(param,param2){param2.some='bla';}}"
Deserialize:
Var myObj = eval('('+text+')');//To UnSerialize
Result:
Object {cons: Array[1], func: function, spoof: function}
Well, the type of an element is not standardly serialized, so you should add it manually. For example
var myobject = new MyClass1("5678999", "text");
var toJSONobject = { objectType: myobject.constructor, objectProperties: myobject };
console.log(JSON.stringify(toJSONobject));
Good luck!
edit: changed typeof to the correct .constructor. See https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/constructor for more information on the constructor property for Objects.
This might be useful.
http://nanodeath.github.com/HydrateJS/
https://github.com/nanodeath/HydrateJS
Use hydrate.stringify to serialize the object and hydrate.parse to deserialize.
You can use a named function on the constructor.
MyClass1 = function foo(id, member) {
this.id = id;
this.member = member;
}
var myobject = new MyClass1("5678999", "text");
console.log( myobject.constructor );
//function foo(id, member) {
// this.id = id;
// this.member = member;
//}
You could use a regex to parse out 'foo' from myobject.constructor and use that to get the name.
Below is another way by which we can JSON data with JSON.stringify() function
var Utils = {};
Utils.MyClass1 = function (id, member) {
this.id = id;
this.member = member;
}
var myobject = { MyClass1: new Utils.MyClass1("5678999", "text") };
alert(JSON.stringify(myobject));
function ArrayToObject( arr ) {
var obj = {};
for (var i = 0; i < arr.length; ++i){
var name = arr[i].name;
var value = arr[i].value;
obj[name] = arr[i].value;
}
return obj;
}
var form_data = $('#my_form').serializeArray();
form_data = ArrayToObject( form_data );
form_data.action = event.target.id;
form_data.target = event.target.dataset.event;
console.log( form_data );
$.post("/api/v1/control/", form_data, function( response ){
console.log(response);
}).done(function( response ) {
$('#message_box').html('SUCCESS');
})
.fail(function( ) { $('#message_box').html('FAIL'); })
.always(function( ) { /*$('#message_box').html('SUCCESS');*/ });
I was having some issues using the above solutions with an "associative array" type object. These solutions seem to preserve the values, but they do not preserve the actual names of the objects that those values are associated with, which can cause some issues. So I put together the following functions which I am using instead:
function flattenAssocArr(object) {
if(typeof object == "object") {
var keys = [];
keys[0] = "ASSOCARR";
keys.push(...Object.keys(object));
var outArr = [];
outArr[0] = keys;
for(var i = 1; i < keys.length; i++) {
outArr[i] = flattenAssocArr(object[keys[i]])
}
return outArr;
} else {
return object;
}
}
function expandAssocArr(object) {
if(typeof object !== "object")
return object;
var keys = object[0];
var newObj = new Object();
if(keys[0] === "ASSOCARR") {
for(var i = 1; i < keys.length; i++) {
newObj[keys[i]] = expandAssocArr(object[i])
}
}
return newObj;
}
Note that these can't be used with any arbitrary object -- basically it creates a new array, stores the keys as element 0, with the data following it. So if you try to load an array that isn't created with these functions having element 0 as a key list, the results might be...interesting :)
I'm using it like this:
var objAsString = JSON.stringify(flattenAssocArr(globalDataset));
var strAsObject = expandAssocArr(JSON.parse(objAsString));

Categories

Resources