How can I convert a JavaScript associative array into JSON?
I have tried the following:
var AssocArray = new Array();
AssocArray["a"] = "The letter A"
console.log("a = " + AssocArray["a"]);
// result: "a = The letter A"
JSON.stringify(AssocArray);
// result: "[]"
Arrays should only have entries with numerical keys (arrays are also objects but you really should not mix these).
If you convert an array to JSON, the process will only take numerical properties into account. Other properties are simply ignored and that's why you get an empty array as result. Maybe this more obvious if you look at the length of the array:
> AssocArray.length
0
What is often referred to as "associative array" is actually just an object in JS:
var AssocArray = {}; // <- initialize an object, not an array
AssocArray["a"] = "The letter A"
console.log("a = " + AssocArray["a"]); // "a = The letter A"
JSON.stringify(AssocArray); // "{"a":"The letter A"}"
Properties of objects can be accessed via array notation or dot notation (if the key is not a reserved keyword). Thus AssocArray.a is the same as AssocArray['a'].
There are no associative arrays in JavaScript. However, there are objects with named properties, so just don't initialise your "array" with new Array, then it becomes a generic object.
Agreed that it is probably best practice to keep Objects as objects and Arrays as arrays. However, if you have an Object with named properties that you are treating as an array, here is how it can be done:
let tempArr = [];
Object.keys(objectArr).forEach( (element) => {
tempArr.push(objectArr[element]);
});
let json = JSON.stringify(tempArr);
I posted a fix for this here
You can use this function to modify JSON.stringify to encode arrays, just post it near the beginning of your script (check the link above for more detail):
// Upgrade for JSON.stringify, updated to allow arrays
(function(){
// Convert array to object
var convArrToObj = function(array){
var thisEleObj = new Object();
if(typeof array == "object"){
for(var i in array){
var thisEle = convArrToObj(array[i]);
thisEleObj[i] = thisEle;
}
}else {
thisEleObj = array;
}
return thisEleObj;
};
var oldJSONStringify = JSON.stringify;
JSON.stringify = function(input){
if(oldJSONStringify(input) == '[]')
return oldJSONStringify(convArrToObj(input));
else
return oldJSONStringify(input);
};
})();
You might want to push the object into the array
enter code here
var AssocArray = new Array();
AssocArray.push( "The letter A");
console.log("a = " + AssocArray[0]);
// result: "a = The letter A"
console.log( AssocArray[0]);
JSON.stringify(AssocArray);
Related
In the example below, the array2.length is only 10, while in my mind, it should be 13.
Why does the "string keyed" indexes not increase the length of the array?
I can store things and still access it, and the VS debugger shows that those arrays are being stored properly. So why is the length not increased?
var array2 = new Array();
array2["a"] = new Array();
array2["b"] = new Array();
array2["c"] = new Array();
for (var i = 0; i < 10; ++i)
array2[i] = new Array();
var nothing = "";
for (var i = 0; i < array2.length; ++i)
nothing = "";
Javascript arrays cannot have "string indexes". A Javascript Array is exclusively numerically indexed. When you set a "string index", you're setting a property of the object. These are equivalent:
array.a = 'foo';
array['a'] = 'foo';
Those properties are not part of the "data storage" of the array.
If you want "associative arrays", you need to use an object:
var obj = {};
obj['a'] = 'foo';
Maybe the simplest visualization is using the literal notation instead of new Array:
// numerically indexed Array
var array = ['foo', 'bar', 'baz'];
// associative Object
var dict = { foo : 42, bar : 'baz' };
Because the length is defined to be one plus the largest numeric index in the array.
var xs = [];
xs[10] = 17;
console.log( xs.length ); //11
For this reason, you should only use arrays for storing things indexed by numbers, using plain objects instead if you want to use strings as keys. Also, as a sidenote, it is a better practice to use literals like [] or {} instead of new Array and new Object.
You're not adding items to the array; you're adding properties to the Array object.
As said above, use object for associative arrays.
If you don't you won't necessarily notice you're doing it wrong, until you innocently use "length" as an array index :
var myArray = [];
myArray["foo"] = "bar"; //works
console.log(myArray["foo"]) //print "bar"
myArray["length"] = "baz" //crash with a "RangeError: Invalid array length"
That is because you are replacing the length attribute of an array with a String, which is invalid.
"string keyed" indexes are not indexes at all, but properties. array2["a"] is the same as saying array2.a. Remember that you can set properties on any kind of variable in javascript, which is exactly what you're doing here.
You can push object to array, it will automatically get indexed (integer). If you want to add index as you want then you want to make it as object
If you want to use an object's properties as if they were like instances of a string indexed array, the work around for the length is:
var myArray = new Array();
myArray["a"] = 'foo';
myArray["b"] = 'bar';
myArray["c"] = 'baz';
let theLength = Object.keys(myArray).length
I must be missing something here, but the following code (Fiddle) returns an empty string:
var test = new Array();
test['a'] = 'test';
test['b'] = 'test b';
var json = JSON.stringify(test);
alert(json);
What is the correct way of JSON'ing this array?
JavaScript arrays are designed to hold data with numeric indexes. You can add named properties to them because an array is a type of object (and this can be useful when you want to store metadata about an array which holds normal, ordered, numerically indexed data), but that isn't what they are designed for.
The JSON array data type cannot have named keys on an array.
When you pass a JavaScript array to JSON.stringify the named properties will be ignored.
If you want named properties, use an Object, not an Array.
const test = {}; // Object
test.a = 'test';
test.b = []; // Array
test.b.push('item');
test.b.push('item2');
test.b.push('item3');
test.b.item4 = "A value"; // Ignored by JSON.stringify
const json = JSON.stringify(test);
console.log(json);
Nice explanation and example above. I found this (JSON.stringify() array bizarreness with Prototype.js) to complete the answer. Some sites implements its own toJSON with JSONFilters, so delete it.
if(window.Prototype) {
delete Object.prototype.toJSON;
delete Array.prototype.toJSON;
delete Hash.prototype.toJSON;
delete String.prototype.toJSON;
}
it works fine and the output of the test:
console.log(json);
Result:
"{"a":"test","b":["item","item2","item3"]}"
I posted a fix for this here
You can use this function to modify JSON.stringify to encode arrays, just post it near the beginning of your script (check the link above for more detail):
// Upgrade for JSON.stringify, updated to allow arrays
(function(){
// Convert array to object
var convArrToObj = function(array){
var thisEleObj = new Object();
if(typeof array == "object"){
for(var i in array){
var thisEle = convArrToObj(array[i]);
thisEleObj[i] = thisEle;
}
}else {
thisEleObj = array;
}
return thisEleObj;
};
var oldJSONStringify = JSON.stringify;
JSON.stringify = function(input){
if(oldJSONStringify(input) == '[]')
return oldJSONStringify(convArrToObj(input));
else
return oldJSONStringify(input);
};
})();
Another approach is the JSON.stringify() replacer function param. You can pass a 2nd arg to JSON.stringify() that has special handling for empty arrays as shown below.
const arr = new Array();
arr.answer = 42;
// {"hello":"world","arr":{"answer":42}}
JSON.stringify({ hello: 'world', arr }, function replacer(key, value) {
if (Array.isArray(value) && value.length === 0) {
return { ...value }; // Converts empty array with string properties into a POJO
}
return value;
});
Alternatively you can use like this
var test = new Array();
test[0]={};
test[0]['a'] = 'test';
test[1]={};
test[1]['b'] = 'test b';
var json = JSON.stringify(test);
alert(json);
Like this you JSON-ing a array.
Json has to have key-value pairs. Tho you can still have an array as the value part. Thus add a "key" of your chousing:
var json = JSON.stringify({whatver: test});
I have a code :
var index = 100;
var arr =[];
arr[index.toString()] = "Hello"
The result : index still known as integer not a string. Anyone can explain what's wrong with my code?
You have to declare associative arrays using {}, which creates a new object, because in JavaScript, arrays always use numbered indexes.
You need to declare an object: var arr={};
arrays use numbered indexes.
objects use named indexes.
var index = 100;
var arr ={};
arr[index.toString()] = "Hello";
console.log(arr);
How to make associative array with number as string in Javascript
JavaScript doesn't have associative arrays in the sense that term is frequently used. It has objects, and as of ES2015 (aka "ES6"), it has Maps.
The result : index still known as integer not a string. Anyone can explain what's wrong with my code?
The index variable's value is still a number, yes, because you haven't done anything to change it. But the index in the array is a string (and would be even if you didn't use .toString()), because standard arrays aren't really arrays at all1, they're objects with special handling of a class of properties (ones whose names are strings that fit the spec's definition of an array index), a special length property, and that use Array.prototype as their prototype.
Here's proof that array indexes are strings:
var a = [];
a[0] = "zero";
for (var name in a) {
console.log("name == " + name + ", typeof name == " + typeof name);
}
That said, you don't want to use an array when you want a generic object or map.
Here's using a generic object for name/value mappings:
var o = Object.create(null);
var name = "answer";
o[name] = 42;
console.log(o[name]); // 42
The property names in objects are strings or (as of ES2015) Symbols. I used Object.create(null) to create the object so it wouldn't have Object.prototype as its prototype, since that gives us properties (toString, valueOf, etc.) that we don't want if we're using the object as a map.
Here's using a Map:
var m = new Map();
var name = "answer";
m.set(name, 42);
console.log(m.get(name)); // 42
The main advantages Maps have over objects are:
Their keys can be anything, not just strings or Symbols
They're iterable, so you can use for-of to loop through the mappings they contain
Maps have a size property telling you how many entries they have
Maps guarantee that iteration of their entries is performed in the order the entries were added to the map
With ES6, you could use a Map, which holds any type as key.
var map = new Map;
map.set(100, "Hello");
map.set('100', "Foo");
console.log(map.get(100)); // 'Hello'
console.log(map.get('100')); // 'Foo'
console.log([...map]);
JavaScript does not support arrays with named indexes, in JavaScript, arrays always use numbered indexes.
If you use a named index, JavaScript will redefine the array to a standard object.
After that, all array methods and properties will produce incorrect results.
As you can see in the following example:
var person = [];
person["firstName"] = "John";
person["lastName"] = "Doe";
person["age"] = 46;
var x = person.length; // person.length will return 0
console.log(x);
var y = person[0]; // person[0] will return undefined
console.log(y);
I have javascript objects that follow this pattern. Keys are to the left of the = sign, values to the right. The keys that are duplicates need to be concatenated to one key while keeping all the values.
var arrUnique = ['arTitle=randomword','arTitle=random','beTitle=rand1','bnTitle=whatever','caTitle=mango','caTitle=mangoes']
Becomes this string:
arTitle = ['randomword','random' ], beTitle = ['rand1'], bnTitle = ['whatever'], caTitle = ['mango','mangoes']
Here is where I am at so far. Create an object with all the keys using regex. Then create a regex construction which loops through each object in keys and pushes to x only when it matches more then 1.
var keys = (/\w{2}Title=/gi);
var x = [];
for (i = 0; i < arrUniqueCount; i++){
var regexp = new RegExp(keys[i], "gi");
var str2 = arrUniqueString.match(regexp).length;
if (str2 > 1){
x.push(regexp[i])}
}
alert("repeats: " + x);
Next I was thinking of using regex to replace and match etc to finally get my outcome. I am finding this stage difficult. Would anybody mind sharing a better way?
I would go the route of just sliptting at the '=' sign then adding them to an object based on the key at index position 0 of that split.
var arrUnique = ['arTitle=randomword', 'arTitle=random', 'beTitle=rand1', 'bnTitle=whatever', 'caTitle=mango', 'caTitle=mangoes'];
//object to collect the final result in
var result = {};
//go through each item and split on the equal
//this will create an array or arrays that contain your key/value
arrUnique.map(function(x) {
return x.split("=");
}).forEach(function(item) {
//if the key doesn;t yet exist in the object declare it as an empty array
if (!result[item[0]]) {
result[item[0]] = [];
}
//push the value onto this key
result[item[0]].push(item[1]);
});
console.log(result);
How can I convert a JavaScript associative array into JSON?
I have tried the following:
var AssocArray = new Array();
AssocArray["a"] = "The letter A"
console.log("a = " + AssocArray["a"]);
// result: "a = The letter A"
JSON.stringify(AssocArray);
// result: "[]"
Arrays should only have entries with numerical keys (arrays are also objects but you really should not mix these).
If you convert an array to JSON, the process will only take numerical properties into account. Other properties are simply ignored and that's why you get an empty array as result. Maybe this more obvious if you look at the length of the array:
> AssocArray.length
0
What is often referred to as "associative array" is actually just an object in JS:
var AssocArray = {}; // <- initialize an object, not an array
AssocArray["a"] = "The letter A"
console.log("a = " + AssocArray["a"]); // "a = The letter A"
JSON.stringify(AssocArray); // "{"a":"The letter A"}"
Properties of objects can be accessed via array notation or dot notation (if the key is not a reserved keyword). Thus AssocArray.a is the same as AssocArray['a'].
There are no associative arrays in JavaScript. However, there are objects with named properties, so just don't initialise your "array" with new Array, then it becomes a generic object.
Agreed that it is probably best practice to keep Objects as objects and Arrays as arrays. However, if you have an Object with named properties that you are treating as an array, here is how it can be done:
let tempArr = [];
Object.keys(objectArr).forEach( (element) => {
tempArr.push(objectArr[element]);
});
let json = JSON.stringify(tempArr);
I posted a fix for this here
You can use this function to modify JSON.stringify to encode arrays, just post it near the beginning of your script (check the link above for more detail):
// Upgrade for JSON.stringify, updated to allow arrays
(function(){
// Convert array to object
var convArrToObj = function(array){
var thisEleObj = new Object();
if(typeof array == "object"){
for(var i in array){
var thisEle = convArrToObj(array[i]);
thisEleObj[i] = thisEle;
}
}else {
thisEleObj = array;
}
return thisEleObj;
};
var oldJSONStringify = JSON.stringify;
JSON.stringify = function(input){
if(oldJSONStringify(input) == '[]')
return oldJSONStringify(convArrToObj(input));
else
return oldJSONStringify(input);
};
})();
You might want to push the object into the array
enter code here
var AssocArray = new Array();
AssocArray.push( "The letter A");
console.log("a = " + AssocArray[0]);
// result: "a = The letter A"
console.log( AssocArray[0]);
JSON.stringify(AssocArray);