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);
Related
I want to transform this object so that I can call it that way
cars.ox, bikes.ox
var baseValue = [
{
'2014-12-01': {
'cars;ox;2014-12-01':100,
'cars;ot;2014-12-01':150,
'bikes;ox;2014-12-01':50,
'bikes;ot;2014-12-01':80
},
'2014-12-02': {
'cars;ox;2014-12-02':100,
'cars;ot;2014-12-02':150,
'bikes;ox;2014-12-02':50,
'bikes;ot;2014-12-02':80
}
}
]
I try do this in many ways, but at the end i completely lost all hope.
var category = []
var obj = baseValue[0]
Object.keys(obj).forEach(function(key) {
var dane = obj[key]
Object.keys(dane).forEach(function(key) {
splitted = key.split(';')
var category = splitted[0]
var serviceName = splitted[1];
})
})
I would be grateful if anyone help me with this
I think you were close, you just need to create objects if they do not exist for the keys you want. Perhaps something like this.
var obj = baseValue[0]
var result = {};
Object.keys(obj).forEach(function(key) {
var dane = obj[key]
Object.keys(dane).forEach(function(key) {
splitted = key.split(';')
var category = splitted[0]
var serviceName = splitted[1];
if(!result[category]) {
result[category] = {};
}
if(!result[category][serviceName]) {
result[category][serviceName] = [];
}
result[category][serviceName].push(dane[key]);
})
});
http://jsfiddle.net/6c5c3qwy/1/
(The result is logged to the console.)
I lately was experimenting with the object serialization in JavaScript. I have already been looking through some of the questions concerning the serialization and deserialization of predefined object in Javascript, but I am looking for a more general solution. An example of this would be:
function anObject(){
var x = 1;
this.test = function(){return x;};
this.add = function(a){x+a;};
}
var x = new anObject();
x.add(2);
console.log(x.test());
>>> 3
var y = deserialize(serialize(x));
console.log(y.test());
>>> 3
Is there a way to serialize this object and deserialize it, such that the deserialized object still have access to the local variable x without the use of the prototype of that object (like in this solution)?
I have already tried by just storing the function as a string and evaluating it again, but then the state of an object can not be saved.
What you are trying to do is not possible without code introspection and code re-writing which I think is not a good idea. However, what about something like this?
function AnObject() {
var x = 1;
this.x = function () { return x; };
this.addToX = function (num) { x += num; };
this.memento = function () {
return { x: x };
};
this.restoreState = function (memento) {
x = memento.x;
};
}
var o = new AnObject();
o.addToX(2);
o.x(); //3
var serializedState = JSON.stringify(o.memento()),
o = new AnObject();
o.restoreState(JSON.parse(serializedState));
o.x(); //3
However, please note that having priviledged members comes at a great cost because you lose the benefits of using prototypes. For that reason I prefer not enforcing true privacy and rely on naming conventions such as this._myPrivateVariable instead (unless you are hiding members of a module).
Thanks for the responses. While the answer from plalx works perfectly for specific objects, I wanted to have something more general which just works for any object you throw at it.
Another solution one can use is something like this:
function construct(constructor, args, vars) {
function Obj() {
var variables = vars
return constructor.apply(this, args);
}
Obj.prototype = constructor.prototype;
return new Obj();
}
function addFunction(anObject, aFunction, variables) {
var objectSource = anObject.toString();
var functionSource = aFunction.toString();
objectSource = objectSource.substring(0,objectSource.length-1);
var functionName = functionSource.substring(9, functionSource.indexOf('('));
var functionArgs = functionSource.substring(functionSource.indexOf('('), functionSource.indexOf('{')+1);
var functionBody = functionSource.substring(functionSource.indexOf('{')+1, functionSource.length);
return objectSource + "this." + functionName + " = function" +
functionArgs + "var variables = " + variables + ";\n" + functionBody + "}";
}
function makeSerializable(anObject) {
var obj = JSON.stringify(anObject, function(key, val) {
return ((typeof val === "function") ? val+'' : val);
});
var variables = [];
while(obj.indexOf("var") > -1) {
var subString = obj.substring(obj.indexOf("var")+3, obj.length-1);
while (subString[0] == " ")
subString = subString.replace(" ", "");
var varEnd = Math.min(subString.indexOf(" "), subString.indexOf(";"));
var varName = subString.substring(0, varEnd);
variables.push(varName);
obj = obj.replace("var","");
}
var anObjectSource = addFunction(anObject,
function serialize(){
var vars = [];
console.log("hidden variables:" + variables);
variables.forEach(function(variable) {
console.log(variable + ": " + eval(variable));
vars += JSON.stringify([variable, eval(variable)]);
});
var serialized = [];
serialized.push(vars);
for (var func in this){
if (func != "serialize")
serialized.push([func, this[func].toString()]);
}
return JSON.stringify(serialized);
},
JSON.stringify(variables));
anObject = Function("return " + anObjectSource)();
var params = Array.prototype.slice.call(arguments);
params.shift();
return construct(anObject, params, variables);
}
This allows you to serialize all elements of any object, including the hidden variables. The serialize() function can then be replaced by a custom string representation for the hidden variables, which can be used when deserializing the string representation to the object.
usage:
function anObject(){
var x = 1;
var y = [1,2];
var z = {"name": "test"};
this.test = function(){return x;};
this.add = function(a){x+a;};
}
var test = makeSerializable(anObject)
test.serialize()
>>>["[\"x\",1][\"y\",[1,2]][\"z\",{\"name\":\"test\"}]",["test","function (){return x;}"],["add","function (a){x+a;}"]]
I've been playing around with javascript and casperjs. I have the following lines of code.
casper.thenOpen('somesite', function() {
console.log('clicked ok, new location is ' + this.getCurrentUrl());
// Get info on all elements matching this CSS selector
var town_selector = 'div tr';
var town_names_info = this.getElementsInfo(town_selector); // an array of object literals
// Pull out the town name text and push into the town_names array
var town_names = [];
for (var i = 0; i < town_names_info.length; i++) {
town_names.push(town_names_info[i].text.trim());}
// Dump the town_names array to screen
utils.dump(town_names);
casper.capture('capture5.png');
});
my output is this.
[
"Address:\n \n address",
"City:\n \ncity",
"State:\n \nstate",
"Zip:\n \nzip",
]
how can I make it json? like this.
{
"Address":"address",
"City":"city",
"State":"state",
"Zip":"zip"
}
Thanks in advance.
You can use something like this:
function arrayToObject(arr) {
var out = {};
arr.forEach(function (element) {
var keyvalue = element.replace(/[\n\s]+/, '').split(':');
var key = keyvalue[0];
var value = keyvalue[1];
out[key] = value;
});
return out;
}
then you can do:
var json = JSON.stringify(arrayToObject(myArray));
Update:
> How can I change this to split only the first occurrence of colon?
Use this:
arr.forEach(function (element) {
var keyvalue = element.replace(/[\n\s]+/, '');
var key = keyvalue.substring(0, element.indexOf(':'));
var value = keyvalue.substring(key.length + 1);
out[key] = value;
});
I have a string like "word_count". How can I transform it to "WordCount" in an elegant way using JavaScript? My decision seems too complicated to me. I'll be very grateful for your help.
function titleCase(str)
{
return str.split("_")
.map(function (s) { return s.charAt(0).toUpperCase() + s.slice(1); })
.join("");
}
Take a look at this. I don't want to just copy paste everything here, but it seems to be just what you're looking for.
Here is the function modified to fit your request:
String.prototype.toCamel = function(){
return this.replace(/((^|\_)[a-z])/g, function($1){
return $1.toUpperCase().replace('_','');});
};
And here it is in action.
You can use a regular expression to match either a letter at the start of the string or a letter after an underscore, and use a callback to turn the letter into uppercase:
s = s.replace(/(?:^|_)([a-z])/g, function(m, g){
return g.toUpperCase();
});
Demo: http://jsfiddle.net/Guffa/ByU6P/
Simple, like this:
var string = "word_count".split("_");
for(var i = 0; i<string.length;i++) {
string[i] = string[i].charAt(0).toUpperCase() + string[i].substr(1);
}
var myNiceString = string.join();
If you want to add it to the String object, you can do this:
String.prototype.titleCase = function() {
var split = this.split("_");
for(var i = 0; i<split.length;i++) {
split[i] = split[i].charAt(0).toUpperCase() + split[i].substr(1);
}
return split.join("");
}
You'd call it like "word_count".titleCase();
You can use a function like the following:
var Pascalize = function(word) {
var x = word;
result = '';
if(-1 != word.indexOf('_')) {
x = word.split('_');
for(var i=0;i<x.length;i++) {
result += x[i].substr(0, 1).toUpperCase() + x[i].substr(1);
}
}
if('' == result) { result = word; }
return result;
};
var PascalCaseString = Pascalize("this_is_a_test");
// PascalCaseString value is now 'ThisIsATest'
Here's a working example
var str = "word_count";
var re = /\b(.)([^_]+)_(.)/;
var newWord = str.replace(re, function(m,f,t,l){ return f.toUpperCase() + t + l.toUpperCase();})
console.log(newWord);
Using jQuery, you could do the following:
var result = '';
$.each('word_count'.split('_'), function(idx,elem){
result = result + elem.substr(0,1).toUpperCase() + elem.substr(1);
});
New version (works with any amount of _):
function fixString(sString) {
var aWords = sString.split("_"),
sResults = "";
for (var i in aWords)
sResults += aWords[i].charAt(0).toUpperCase() + aWords[i].slice(1);
return sResults;
}
The compressed form:
function fixString(c){var d=c.split("_"),a="";for(var b in d){a+=d[b].charAt(0).toUpperCase()+d[b].slice(1)}return a};
Old:
function fixString(sString) {
return sString.replace(/(.*)_(.*)/, function(sWhole, $1, $2, sWTF) {
return ucfirst($1) + ucfirst($2);
} )
function ucfirst (str) {
str += '';
var f = str.charAt(0).toUpperCase();
return f + str.substr(1);
}
}
... or the compressed version:
function fixString(b){return b.replace(/(.*)_(.*)/,function(e,c,f,d){return a(c)+a(f)});function a(d){d+="";var c=d.charAt(0).toUpperCase();return c+d.substr(1)}};
Of course, this is used like fixString("word_count") which results in your desired WordCount.
I've looked at all the answer and none did precisely what I wanted. I wanted an idempotent function which converted to camelCase (not PascalCase) and I liked the String prototype extension approach (although obviously this isn't always the best medicine).
Anyway, here's where I ended up:
String.prototype.camelize = function(){
var pascalCase = this.replace(/((^|\_)[a-z])/g, function($1){
return $1.toUpperCase().replace('_','');
});
return pascalCase.charAt(0).toLowerCase() + this.slice(1);
};
var aStringLike = "word_count";
// magic follows
aStringLike = "WordCount";
I need to get the URL search paramentes in an object, for eg; http://example.com/?a=x&b=y&d#pqr should yield {a:x, b:y, d:1}
Below is the method i used to get this, How can i improve this? any suggessions...
var urlParamKeyVals = new Array();
var pieces = new Array();
var UrlParams = {};
if(window.location.search.length){
var urlSearchString = window.location.search;
if(urlSearchString.charAt(0) == '?'){
urlSearchString = urlSearchString.substr(1);
urlParamKeyVals = urlSearchString.split("&");
}
}
for (var i = 0; i<urlParamKeyVals .length; i++) {
pieces = urlParamKeyVals [i].split("=");
if(pieces.length==1){
UrlParams[pieces[0]]=1;
} else {
UrlParams[pieces[0]]=pieces[1];
}
}
UrlParams;
I've made some time ago a small function for the same purpose:
Edit: To handle empty keys as 1:
function getQueryStringValues (str) {
str = str || window.location.search;
var result = {};
str.replace(/([^?=&]+)(?:[&#]|=([^&#]*))/g, function (match, key, value) {
result[key] = value || 1;
});
return result;
}
getQueryStringValues("http://example.com/?a=x&b=c&d#pqr");
// returns { a="x", b="c", d=1 }
function getParams(q){
var p, reg = /[?&]([^=#&]+)(?:=([^&#]*))?/g, params = {};
while(p = reg.exec(q)){
params[decodeURIComponent(p[1])] = p[2] ? decodeURIComponent(p[2]) : 1;
}
return params;
}
getParams(location.search);
-- edit
I extended the regular expression to match also the ¶m (no value) and ¶m= (empty value) cases. In both cases the value 1 is returned. It should also stop extracting on hash (#) character. Decoding values also supported.
jQuery bbq has a nice deparam method if you are trying to look at some very stable code:
http://github.com/cowboy/jquery-bbq/
http://benalman.com/code/projects/jquery-bbq/examples/deparam/
function getObjectFromSearch() {
var search = location.search;
var searchTerms = [];
var obj = {};
if (search !== '') {
search = search.replace(/^\?/,'');
searchTerms = search.split("&");
}
for (var i=0, imax=searchTerms.length; i<imax; i++) {
var ary = searchTerms[i].split("=");
obj[ary[0]] = ary[1];
}
return obj;
}