4

I am storing my array as a mixture of array an array and an object. For example assume this one:

let arrObj = [];
arrObj["x"] = 12;
arrObj.push(12);
arrObj["y"] = 15;
arrObj.push(15);

// result: arrObj = [12, 15, x: 12, y: 15]

so that, I can access the value 12 even using arrObj[0] and arrObj["x"]. And this way, I can do a repeat for on it.

But when I stringify it, the keys x and y get lost:

JSON.stringify(arrObj)
// result: "[12,15]"

How should I maintain those keys and their values?

6
  • 1
    This is not a valid JSON string: "[ 12, 15, 'x': 12, 'y': 15 ]". Even if you output it, you won't be able to parse it as JSON. So it's not clear how this could work without some sort of transformation. Commented Mar 30, 2019 at 6:39
  • That's enough for me to make this structure valid for myself. I mean, at the other end I myself am catching the value, so that I can manipulate that end too. Commented Mar 30, 2019 at 6:42
  • [...arrObj.values()] // [12, 15] is the actual result. Dont confuse with x and y. They are just properties of arrObj array Commented Mar 30, 2019 at 6:46
  • 1
    @ConductedClever Then Pranav C Balan's updated answer using object is abt for your case Commented Mar 30, 2019 at 7:03
  • 1
    Of course @AswinKumar. Thanks. Commented Mar 30, 2019 at 7:03

3 Answers 3

4

While stringifying convert it to an object using spread syntax and later parse and use Array#reduce method to generate the array.

The array keeps the property since Array is also an object in Javascript.

let arrObj = [];
arrObj["x"] = 12;
arrObj.push(12);
arrObj["y"] = 15;
arrObj.push(15);

let json = JSON.stringify({ ...arrObj });

console.log(json);

let parsed = Object.entries(JSON.parse(json)).reduce((arr, [key, value]) => (arr[key] = value, arr), []);

console.log(parsed);

FYI : But it always better to use an Object or Map for key-value pair data, not better that's the right way in my opinion.


UPDATE 1: Or you can use a main object which keeps all additional property and within it create a property which keeps the array as well.

let arrObj = {
  arr: []
};
arrObj["x"] = 12;
arrObj.arr.push(12);
arrObj["y"] = 15;
arrObj.arr.push(15);

let json = JSON.stringify(arrObj);

console.log(json);

let parsed = JSON.parse(json);

console.log(parsed);


UPDATE 2: The second approach cause issue if you are trying to set property named arr(in my case) so keep object values in separate property.

let arrObj = {
  arr: [],
  obj: {}
};
arrObj.obj["x"] = 12;
arrObj.arr.push(12);
arrObj.obj["y"] = 15;
arrObj.arr.push(15);

let json = JSON.stringify(arrObj);

console.log(json);

let parsed = JSON.parse(json);

console.log(parsed);

Sign up to request clarification or add additional context in comments.

6 Comments

Thanks. Map is good in accepting key-value pair and repeating but not serializable.
The second solution also is good but it will break my extension methos: Array.prototype.pushNamed = function (key, value) { this[key] = value; this.push(value); return this; }
@ConductedClever : rewrite it like Object.prototype.pushNamed = function (key, value) { this[key] = value; this.arr.push(value); return this; }
@ConductedClever ;)
@ConductedClever : for the new approach it would be like Object.prototype.pushNamed = function (key, value) { this.obj[key] = value; this.arr.push(value); return this; }
|
0

Arrays should contain numeric-indexed values only. If you want keys in addition to values, use an object:

const obj = {};
obj.x = 12;
obj[0] = 12;
obj.y = 15;
obj[1] = 15;

console.log(JSON.stringify(obj));

for (let i = 0; i in obj; i++) {
  console.log(obj[i]);
}

You could also consider using an object that contains both an array and your custom key-value pairs, eg:

const arr = [];
const obj = { arr };
obj.x = 12;
obj.y = 15;
arr.push(12);
arr.push(15);

console.log(JSON.stringify(obj));

10 Comments

I want it to be an array to let foreach on it. This is not the answer of mine.
If you want to preserve the arbitrary keys over stringification, use an object instead, and then transform it into an array when you need to use forEach.
Stringified arrays cannot have arbitrary key-value pairs. If you need arbitrary key-value pairs to be saved over serialization, you have to use an object, not an array.
If you do that, the result will not be valid JSON, and won't be parseable by anything but a custom parser you build, which would be difficult and a bad idea.
And if it's a custom parser, then by definition, you're not dealing with JSON, since JSON parses don't work. Also, wanting to foreach the array is a bad justification for breaking standards.
|
0

Here is a fancy 1 liner solution:

let arrObj = [];
    arrObj["x"] = 12;
    arrObj.push(12);
    arrObj["y"] = 15;
    arrObj.push(15);

var string = JSON.stringify(Object.keys(arrObj).reduce((acc, cur) => ((acc[cur] = arrObj[cur]), acc), {}));

console.log(string);

P.S: I thought it's worthy to mention that you might encounter an unexpected behaviour because in JS, there is no guarantee that object properties are ordered (as you wanted to). Does JavaScript Guarantee Object Property Order?

1 Comment

Although the order is not important for me but the stringified object is not as desired. Thanks.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.