js array to json but some value disappear - javascript

window.onload = function() {
var arr = new Array;
var jsonObj = {
"123": "234"
};
arr['v'] = "234";
arr[0] = jsonObj;
arr[1] = jsonObj;
console.log(JSON.stringify(arr));
}
The above code result is :
[{"123":"234"},{"123":"234"}]
I don't know why the arr['v'] disappeared?

Object and Array are not parsed to JSON the same way.
an Array will only include the numeric keys, and an Object will include all of its keys:
var Arr = [], Obj ={};
Arr[0] = Obj[0] = 'a';
Arr[1] = Obj[2] = 'b';
Arr['key'] = Obj['key'] = 'c';
console.log(JSON.stringify(Arr));
console.log(JSON.stringify(Obj));
so in your case, you could simply use an Onject instead of an array:
var arr = new Object;
var jsonObj = {"123":"234"};
arr['v'] = "234";
arr[0] = jsonObj;
arr[1] = jsonObj;
console.log(JSON.stringify(arr));

Actually, JSON.stringify will ignore non-numeric keys in Array during the Array JSON serialization. From the latest ECMA Spec, in section "24.3.2.4 Runtime Semantics: SerializeJSONArray ( value )", we know JSON.stringify only utilizes length of Array and related numeric keys to do the serialization, and Array length will not be affected by its non-numeric keys. So it is now clear why 'v' (non-numeric keys) disappear in your final result.

You can't use a string as an array index, unless it is a string representation of an integer.
Therefore, arr['v'] has no meaning.
This stackoverflow question goes into more detail, but the relevant part:
Yes, technically array-indexes are strings, but as Flanagan elegantly
put it in his 'Definitive guide':
"It is helpful to clearly distinguish an array index from an object
property name. All indexes are property names, but only property names
that are integers between 0 and 232-1 are indexes."

In JavaScript, basically two types of array, Standard array and associative array. Standard array is defined by [], so 0 based type indexes. And in associative array is defined by {}, in this case you can define string as keys. So in your code you are using both is single array, that's not acceptable. So define the another array if you want strings keys.

Related

creating an array, convert it to json and pass it to php

I want to fill an array dynamically with javascript, then convert it to a json string and pass it to php to deal with it.
The problem:
When I define the array like -code 1- the output is as expected:
var feld = {
"key1" : "1",
"key2" : "2",
"key3" : "3"
};
for (key in feld) { console.log (key + "= " + feld[key]); }
var jsonString = JSON.stringify(feld);
console.log(jsonString);
OUTPUT:
key1= 1
key2= 2
key3= 3
{"key1":"1","key2":"2","key3":"3"}
If I define the array like -code 2-
var feld = new Array ();
feld["key1"]="1";
feld["key2"]="2";
feld["key3"]="3";
for (key in feld) { console.log (key + "= " + feld[key]); }
var jsonString = JSON.stringify(feld);
console.log(jsonString);
OUTPUT:
key1= 1
key2= 2
key3= 3
[]
which means, that with code -2- there is nothing to pass to php.
what's wrong ?
"-code 1-" is not an array, it's a non-array object. "-code 2-" is an array, but being used as a non-array object. (And the reason you don't see your non-array properties when you stringify it is that since it's an array, JSON.stringify only serializes the array entries, not the non-array properties.)
What's wrong is that if you want an array, you need to create an array:
var feld = ["1", "2", "3"];
But it sounds like you don't want an array, you really do want an object, like in your first example. If you convert that to JSON and send it to your server, use json_decode to decode it into a PHP object where you can access the key1, key2, and key3 properties to get their values.
You are confusing arrays in js with arrays in php. If in php you can define literal keys for an array like this:
<?php
$a = array( 'key1' => 1);
$a['key1] === 1
in js that is the equivalent of an object rather than an array.
Js is more mathematichal , if you like, with the concept of array,
a = [2, 4, 6];
it is just a list of values/ objects each given by a numeric index.
a[1] === 4
In JavaScript you can attach properties to an array, which will not be member of this array. For example:
let array = new Array(); // Creates empty array: []
array[0] = 123; // Inserts a member to array
console.log(array) // Will output: [123]
array["abc"] = 789 // Attaches a property to array
console.log(array) // Will output: [123], no members were added to array
console.log(array.abc) // Will output: 789
This is possible because Array also acts as an object, so it has members (indexed) and also properties (having keys).
Arrays do not have keys (key0,key2,key3,...), only indexes (0,1,2,...). You probably want either a map or an array. The map is created by code you have attached to the question (first section), the array can be created as following:
var feld = new Array ();
feld[0]="1";
feld[1]="2";
feld[2]="3";
var jsonString = JSON.stringify(feld);
console.log(jsonString);
You have to objectify your array:
...
feld = Object.assign({}, feld);
var jsonString = JSON.stringify(feld);
...

JavaScript. How can I parse a string of vars and turn it into an object with properties

I am trying to parse a string in JS with a series of vars inline. The goal is to turn those vars into an object with name value pairs.
Example:
var hwStr = "color=blue+coreCnt=4+shell=aluminum+wireless=false";
I know I can parse the original string to get an array of name value pairs like this:
varArr = hwStr.split("+");
When I print that array I would get:
>color=blue,
>coreCnt=4,
>shell=aluminum,
>wireless=false
In order to create this object manually it would look like:
var hwSpec = {color: 'blue', coreCnt: 4, shell: 'aluminum', wireless: false};
My question is, how can I use a foreach statement to create an object that would have these as name value pairs.
To be fair JS is not my language, but I know that I SHOULD know this... This is probably a noob Question, any help would be great.
Gary C aka the UnKulMunki
After splitting on the plus signs, you can .reduce() the resulting array to process each key=value pair and add to an object:
var hwStr = "color=blue+coreCnt=4+shell=aluminum+wireless=false";
var obj = hwStr.split("+").reduce(function(o, item) {
item = item.split("=");
o[item[0]] = item[1];
return o;
}, {});
console.log(obj);
This is similar to using .forEach(), except instead of creating an empty object in a variable before calling .forEach() the empty object is passed as an argument to .reduce(). For this particular problem it doesn't make much difference, but in some cases .reduce() saves you having to create a temporary working variable.
EDIT: Note that my code creates all property values as strings - I don't think there's any way to know whether false should be treated as the boolean false or the string "false", unless you want to assume that all values that can be parsed as boolean or number should be treated as boolean or number.
First, you split the string at the + so you get an array of key/value pairs.
Then, you loop through those pairs and split each pair at the = to separate the key from the value. Then you assign the key as a property name and the value as the property value.
var hwStr = "color=blue+coreCnt=4+shell=aluminum+wireless=false";
// Split the string into an array of key/value pairs
var pairs = hwStr.split("+");
// Set up a new, empty object
var newObj = {};
// Loop through the key/value pairs array. The .forEach method takes
// a function as an argument that, itself, receives a value representing
// the current array item being iterated (a single key/value pair from
// the array in this case).
pairs.forEach(function(pair){
// Create a new property on the object with the key of the current pair
// and a value of the value of the current pair.
newObj[pair.split("=")[0]] = pair.split("=")[1];
});
console.log(newObj);
To do this, you have to use JSON's parse method to turn the string to javaScript object literal, this is how to do it:
var arr = hwStr.split("+");
var temp_arr = null;
var hwSpec = null;
var stringToConv = '{'; //string to convert to object literal
//iterate through the array
for (var i = 0; i < arr.length; i++){
temp_arr = arr[i].split("=");
stringToConv += '"' + temp_arr[0] + '":"' + temp_arr[1] + '"';
//check if is the last string in the arr
if (i === arr.length - 1){
stringToConv += '}'
}
else { //add comma
stringToConv += ",";
}
}
//convert to object using JSON
hwSpec = JSON.parse(stringToConv);
//your code here

Named objects and collection of them

not sure how to ask tbh :)
I'm used of PHP's associative arrays so much that I struggle to understand how to create an "named array" of objects.
Example:
I have two arrays, two ints and one boolean. This represents one of my entities. I have multiple entities on which I'm doing some work.
In PHP I would write:
$entitites[$entitity_id]['items'][] = $item;
$entitites[$entitity_id]['items_status'][] = $item_status;
$entitites[$entitity_id]['items_count']++;
and so on..
How do I do this with objects in JS?
var entities = {items:[], items_status: [], items_count: 0};
entities[entity_id].items.push(item)
How does one name his object for later access (via name or in my case, entity_id?)
This code doesnt work for me to this extend that my webpage goes blank without any errors produced :S
I also tried this:
var entities = {};
var entity = {items:[], items_status: [], items_count: 0};
but then I dont know how to always add values to already existing object in entities object and how to call that exact object via name eg. entity_id.
Halp :(
Keep entities as an object. Then you can just go ahead and add each entity_id as a key and an object which has all the details of that entity as the value.
var entities = {};
entities["1234"] = {
"items" : [],
"items_status" : [],
"items_count" : 0
};
There are 2 types involved here: Objects & Arrays.
Arrays are simple and you're probably familiar with them from any other language:
var myArray = []; // this is an empty array
myArray[0] = 1;
myArray[1] = 2;
myArray[2] = 3;
// you could also use "var myArray = [1, 2, 3];" instead
alert(myArray[1]); // alerts the value 2
Note: arrays are actually objects, and can have non-index properties as well
You can also use various array functions such as .push(), .pop(), .shift() and so on to mutate the array instead.
Objects share the square brackets notation, but the purpose is different:
var myObject = {}; // this is an empty object
myObject[0] = 1;
myObject[1] = 2;
myObject[2] = 3;
alert(myObject[1]); // alerts the value 2
// but also...
myObject['prop'] = 4;
alert(myObject['prop']); // alerts the value 4
// and
myObject.prop2 = 5;
alert(myObject.prop2); // alerts the value 5
// and lastly
alert(myObject.prop); // alerts the value 4
So while arrays are accessed by index, objects are accessed by property names.
As for your entities, it looks like an array of objects. Lets see how we can do that:
function Entity() {
this.items = [];
this.items_status = [];
this.items_count = 0;
}
var entitites = [];
entities.push(new Entity());
entities[0].items = [1, 2, 3];
entities[0].items_status = ['good', 'good', 'poor'];
entities[0].items_count = 3;
Or you can wrap insertion in a more elegant function:
Entity.prototype.insert(item, status) {
this.items.push(item);
this.items_status.push(status);
this.items_count++;
}
entities[0].insert(4, 'excellent!');
If you want to keep control of the indexes in your JS array you can do so by not using .push() :
var entities = [];
entities[5] = {items:[], items_status:[], items_count:0};
Just replace 5 by your integer entity_id variable, and there you go.
You can use a regular javascript object to create the associative array you're looking for.
Actually it's PHP's implementation that's abit off but all they do is call it different (associative array) to most other language that simply refer to it as an object or hash.
You can use numeric keys in JS and still access them with the [] square brackets.
It works like this:
var my_obj = {};
my_obj[5] = 'any value';
console.log(my_obj); // {5: 'any value'}
JS will not add any redundant undefined to missing indexes either so when looping over the collection you won't loop over undefined.
Also, I can access the object by using the key as a string or as number so you won't have to check if the key is the right type. Taken from the above example:
console.log(my_obj['5']); // 'any value'
console.log(my_obj[5]); // 'any value'
JS Objects are the equivelant of PHP assoc arrays except JS objects are much more flexible than PHP's associative arrays.
The only downside to this is that you can't have duplicate keys.
No two keys may exist that share the same name, in an array if you .push(an_item) it will create a new index making even a duplicate data entry unique but when overwriting a key with a new value only the last value will persist, mind that :)

Convert array to Object by JSON.parse

var arr=[];
arr['first']='val1';
arr['second']='val2';
var json=JSON.stringify(arr);
var obj=JSON.parse(json); //obj is array
Can I return object {"first":"val1","second":"val2"} ?
P.S.: I read Convert Array to Object topic
I'm interested in this way of the function
If somebody has abused arrays like that, JSON does not help you. It will only serialize the numeric indices of Array objects, nothing else. Copy the properties by hand:
var obj = {};
for (var prop in arr)
if (arr.hasOwnProperty(prop)) // don't copy enumerables from Array.prototype
obj[prop] = arr[prop];
console.log(obj); // {"first":"val1","second":"val2"}
You shouldn't use an array to represent this:
Do this instead:
var obj = {first:"val1",second:"val2"};
Just define the object directly . Stringify and parsing is not necessary

Serializing a Javascript object with contained arrays to json?

I have a javascript object that contains a few objects that contain associative arrays. I've been trying to use the json2.js library's stringify function but the output doesn't contain the arrays held in the contained object members.
In my code I start with something like this
obj = {"arr1" : [], "arr2" : [], "arr3" : []};
then I add to it with loops that fill each of the contained arrays
obj[arr*].push[arritem*];
obj[arr*][arritem*] = something;
The arr* and arritem* I put in just to represent the variable I am putting in for the loops.
I try Json.stringify(obj) but the string I get back is
'{"arr1" : [0], "arr2" : [0], "arr3" : [0]}'
I would like to see the ouput as
'{"arr1" : [ "arritem1" : something, "arritem2" : something2], "arr2" : [ "arritem1" : something, "arritem2" : something2], "arr3" : [ "arritem1" : something, "arritem2" : something2]}'
is there a better library for this or is there something I have to do before strinfying?
var obj = {"arr1" : [], "arr2" : [], "arr3" : []};
console.log(JSON.stringify(obj));
Works for me.
Filling the arrays works too.
Update
You imply that you are trying to add elements with non-numeric keys to arrays.
This is not valid. In particular, your desired output is not valid JSON. Arrays have only numeric keys, and they are not included in the JSON itself as they are implicitly, sequentially defined.
Arrays are a special type of Object, which handles numeric indexes for you.
var arr = []; // Create array.
arr.push(1); // There is now one element, with index 0 and value 1.
arr["txt"] = 2; // You tried to create a new element,
// but didn't use .push and gave a non-numeric key.
// This broke your array.
console.log(JSON.stringify(arr));
// Output: [1]
Live demo.
Long story short... don't do this. If you want an "associative array", stick with basic objects:
var obj = {}; // Create object.
obj[0] = 1; // There is now one element, with key "0" and value 1.
obj["txt"] = 2; // There is now a second element, with key "txt" and value 2.
console.log(JSON.stringify(arr));
// Output: {"0":1,"txt":2}
Live demo.
obj.toSource()
this will convert your array to source string.

Categories

Resources