JSON.stringify custom formatting - javascript

I am looking for a way to write a JSON object to a file, but maintaining the same formatting with the orignal.
I have managed to write the content using writeFileSync(path,data) and JSON.stringify() but struggling to figure out how to customise the formatting. The options JSON.stringify accepts seem to format only the number of spaces.
Is there any way tho using JSON.stringify to generate the following formatting
{
"key1" :{"key": "value1","key": "value2"},
"key2" :{"key": "value1","key": "value2"}
}
instead of the one generated by default
{
"key1":
{
"key": "value1",
"key": "value2"
},
"key2":
{
"key": "value1",
"key": "value2"
},
}

Unfortunately not, you can use the space argument to define the spacing of the objects as they fall in on the tree. What you're proposing would require custom formatting using something like regular expressions to format the strings after you stringify it.
Below you'll find some sample code to do what you're looking to do however. You can append all of these into a single command like JSON.stringify(myJSON, null, ' ').replace(/: \{\n\s+/g, ': {').replace(/",\n\s+/g, ', ').replace(/"\n\s+\}/g, '}');, however so you could see what I did, I broke it down step by step.
const myJSON = {
"key1":{"key": "value1","key2": "value2"},
"key2":{"key": "value1","key2": "value2"}
}
let myString = JSON.stringify(myJSON, null, ' ').replace(/: {/g, `${' '.repeat(5)}: \{`); //Set the key spacing
myString = myString.replace(/: \{\n\s+/g, ': {'); //Bring the child bracket on the same line
myString = myString.replace(/",\n\s+/g, ', '); //Bring all the other objects for that array up
myString = myString.replace(/"\n\s+\}/g, '}'); //Pull the closing bracket on the same line
const myCompactString = JSON.stringify(myJSON, null, ' ').replace(/: {/g, `${' '.repeat(5)}: \{`).replace(/: \{\n\s+/g, ': {').replace(/",\n\s+/g, ', ').replace(/"\n\s+\}/g, '}'); //Done all at once
console.log(`myString: ${myString}`);
console.log(`myCompactString: ${myCompactString}`);

Building on KevynTD's great answer!
to keep Arrays of strings ['song', 'bird'] from changing to {'0': 'song', '1': 'bird'} index keyed objects. Add the if (Array.isArray(this)) obj = this; to the singleLineOBJ function.
const singleLineOBJ = function () {
let obj = { ...this }; // To not change any toJSON
if (Array.isArray(this))
obj = this; // override converting array into object
delete obj.toJSON // To not fall in a stringify loop

I want format like this:
var house = {
family: {
surname: "Smith",
people: 4,
pets: {
dogs: {number:1, names:["toby"]},
cats: {number:2, names:["bob", "boo"]},
platypus: {number:1, names:["perry"], codename: ["agent p"]},
}
},
livingRoom: [
{name:"couch", amount:2},
{name:"shelf", amount:1},
{name:"nightstand", amount:1},
{name:"television", amount:1},
],
bedroom: [
{name:"bed", amount:1},
{name:"wardrobe", amount:1},
{name:"shelf", amount:2},
],
}
It is a similar problem, but with more specific object keys, within a more complex tree of objects, and it started to get quite complicated to do this with just a regex. So, I created a function using toJSON and the stringify replacer as tools to handle this.
The function I created has some limitations, like just being able to define singleLine and multiLine only objects, and not numeric or text lists for example. It also has the limitation of some specific characters that are used for a replacement scheme, they are unusual characters, but look to confirm if you must replace them. The characters are four: '╲' (fake \), '”' (fake "), '→' and '←', if your object contains any of them you can replace them at the very beginning of the function.
Here an example with the function working:
// Custom Stringfy
const customStringify = function (
obj,
replacer,
space = "\t",
{
singlelineObjectKeys = [],
multilineObjectKeys = [],
singlelineChildKeys = [],
multilineChildKeys = [],
singlelineInsideList = [],
}
) {
// WARNING
// - This function will make a mess if your Object contain some of the following characters:
const fakeNewLine = `╗`; // (replace \n in middle of process)
const fakeTab = `╦`; // (replace \t in middle of process)
const fakeQuote = `║`; // (replace " in middle of process)
const startString = `╠`; // (add to start in middle of process)
const endString = `╣`; // (add to end in middle of process)
// So a solution in this case can be replace this chars by others not used (dont use characters that can mess the regex)
// First make a stringify to solve any toJSON in the main object, then copy the main object stringfied to create all the necessary new toJSON
let objModified = JSON.parse(JSON.stringify(obj, replacer));
// Convert an entire object to single line string
const singleLineOBJ = function () {
// To not change any toJSON
const obj = Array.isArray(this) ? [...this] : { ...this };
// To not fall in a stringify loop
delete obj.toJSON;
// Mark the startString and endString
return (
startString +
JSON.stringify(obj)
// Replace all " by fakeQuote
.replace(/"/g, fakeQuote) +
endString
);
};
// Convert an entire object to multi line string
const multiLineOBJ = function () {
// To not change any toJSON
const obj = Array.isArray(this) ? [...this] : { ...this };
// To not fall in a stringify loop
delete obj.toJSON;
// Mark the startString and endString
return (
startString +
JSON.stringify(obj, null, "\t")
// Replace all " by fakeQuote
.replace(/"/g, fakeQuote)
// Replace \n using fakeNewLine
.replace(/\n/g, fakeNewLine)
// Replace \t using fakeTab
.replace(/\t/g, fakeTab) +
endString
);
};
// Checks all keys on the object
const throughEveryKey = function (key, value) {
let obj = this;
// objects inside specific keys to become single-line
if (singlelineObjectKeys.includes(key)) {
obj[key].toJSON = singleLineOBJ;
}
// objects inside specific keys to become multi-line
if (multilineObjectKeys.includes(key)) {
obj[key].toJSON = multiLineOBJ;
}
// objects containing the following keys to become single-line
if (singlelineChildKeys.includes(key)) {
obj.toJSON = singleLineOBJ;
}
// objects containing the following keys to become multi-line
if (multilineChildKeys.includes(key)) {
obj.toJSON = multiLineOBJ;
}
// names of list of objects to each list-item become single-line
if (singlelineInsideList.includes(key)) {
obj[key].forEach(
(objectInsideList) => (objectInsideList.toJSON = singleLineOBJ)
);
}
return value;
};
// Just use stringify to go through all object keys, and apply the function to implement "toJSON" in right places, the result of stringify is not used in this case (WIP)
JSON.stringify(objModified, throughEveryKey);
// Use stringfy with right replacers, end result
return (
JSON.stringify(objModified, null, "\t")
// Put in all start of line the right number of Tabs
.replace(new RegExp("(?:(?<=(?<leadTab>^\t*).+?)(?<newLine>" + fakeNewLine + ")(?=.+?))+", "gm"), "$&$1")
// Replace the fake tab by the real one
.replace(new RegExp(fakeTab, "gm"), "\t")
// Replace the fake new line by the real one
.replace(new RegExp(fakeNewLine, "gm"), "\n")
// Replace the fake quote by the real one
.replace(new RegExp(fakeQuote, "gm"), '"')
// Remove start and end of line from the stringfied object
.replace(new RegExp('"' + startString, "gm"), "")
.replace(new RegExp(endString + '"', "gm"), "")
// Replace tab by custom space
.replace(/(?<=^\t*)\t/gm, space)
);
};
var house = {
family: {
surname: "Smith",
people: 4,
pets: {
dogs: {
number: 1,
names: ["toby"],
},
cats: {
number: 2,
names: ["bob", "boo"],
},
platypus: {
number: 1,
names: ["perry"],
codename: ["agent p"],
},
},
},
livingRoom: [
{
name: "couch",
amount: 2,
},
{
name: "shelf",
amount: 1,
},
{
name: "nightstand",
amount: 1,
},
{
name: "television",
amount: 1,
},
],
bedroom: [
{
name: "bed",
amount: 1,
},
{
name: "wardrobe",
amount: 1,
},
{
name: "shelf",
amount: 2,
},
],
};
console.log("A custom stringify:\n\n");
console.log(
customStringify(house, null, " ", {
singlelineObjectKeys: ["dogs", "cats", "platypus"],
multilineObjectKeys: ["family"],
multilineChildKeys: [],
singlelineChildKeys: [],
singlelineInsideList: ["livingRoom", "bedroom"],
})
);
console.log("\n\n\n");
console.log("A normal stringify:\n\n");
console.log(JSON.stringify(house, null, " "));
You need to pass some information to work, you don't need to use everything, but I'll explain the cases that I left prepared to format between multiLine and singleLine:
singlelineObjectKeys: Put here the keys for objects / arrays that need to be on a single line
multilineObjectKeys: Place here the keys of objects / arrays that need to be formatted in several lines
multilineChildKeys: If you do not want to specify a parent object, as they can have many, specify a child key for the parent object to be formatted on multiple lines
singlelineChildKeys: If you don't want to specify a parent object, as they can have many, specify a child key for the parent object to be formatted on a single line
singlelineInsideList: If you have a list of objects, and you want all objects within that list to be formatted in a single list, put the key for that list here
In the example above the code used was this:
customStringify(house, null, '\t', {
singlelineObjectKeys: ["dogs","cats","platypus"],
multilineObjectKeys: ["family"],
singlelineInsideList: ["livingRoom","bedroom"],
})
But this will result the same for example:
customStringify(house, null, '\t', {
singlelineChildKeys: ["name","names"],
})
As I had researched this in several places and found nothing about it, I register my solution here (which was one of the places I looked for). Feel free to use!
Edit:
Updated to receive lists as single line or multiline on objects, thanks to #mj1701's suggestion.
Updated way to replace newline and tab, made code 20% faster
Old unresolved problem: After defining singlelineInsideList, if you put a multilineObjectKeys that is inside, the code tab has a problem, in progress
I am modifying the code in free time, it is not 100% finished, but it already works in several tested cases.
If you found any bugs, please comment here!

Related

javascript remove text with double inverted comma not working

I have a json object in a table like below
filter: {where: { AND:[{gender: {IN: "Female"}},{age: {LTE: 44}}]}, relativeDateRange: 90}
which I am fetching and need to change, By removing some of the text.
The new json object will look like below
{"filter": {"where": {"gender": {"IN": "Female"}, "age": {"LTE": 54}},"relativeDateRange": 90}}
One way of doing that is to stringify the object and replacing the keyword,
which in my "theory" should work. however by any mean I am not able to replace ('{"AND":') to blank.
The issue is the keyword contains double inverted comma.
below is the code:
s is the json object which contains the wrong json.
var stringified = JSON.stringify(s);
var t1 = stringified.replace("}{",", ").replace("}}]}","}}").replace('{"AND":', '')
var jsonObject = JSON.parse(t1);
console.log("new json:" +jsonObject);
The text which does not have double inverted comma is getting replaced.
Even using regex or escape character is not helping.
Any suggestion
One option you can try is to use the replacer function which is a parameter in JSON.stringify:
// Your initial filter object
const filter = {filter: {where: { AND:[{gender: {IN: "Female"}},{age: {LTE: 44}}]}, relativeDateRange: 90}};
// Define your replacer function:
const replacer = (name, value) => {
if (name === 'where') {
const array = value['AND'];
// Merge array elements or alter your output in any other way
return Object.assign({}, array[0], array[1]);
}
return value;
}
// The resulting output
console.log(JSON.stringify(filter, replacer, 2));
will produce the following output:
{
"filter": {
"where": {
"gender": {
"IN": "Female"
},
"age": {
"LTE": 44
}
},
"relativeDateRange": 90
}
}
I don't think it's the colon that's throwing off your text replacement statement. How about replacing the "AND" string first, before you complicate it by replacing the curley braces? It should not otherwise effect your other replacements.
var t1 = stringified.replace("AND:[","").replace("}{",", ").replace("}}]}","}}");
The final resolution or more precisely the problem i figure out was,
When a josn is stringified, Its add '\' before every word. As for example when below json is stringified.
filter: {where: { AND:[{gender: {IN: "Female"}},{age: {LTE: 44}}]}, relativeDateRange: 90}
it gives the output as
\filter: {\where: { \AND ....
And the simple resolution was to use replace with double backslash as below.
var t1 = stringified.replace('{\\"AND\\":','').replace(/}{/g,",").replace("}}},","}},").replace('{/"/":','')

Create array from json with exceptions to the value

let me show you some working code I have here:
Example that works
[
{
"actual_time":"11:00:00",
"length":"30"
},
{
"actual_time":"13:05:00",
"length":"40"
}
]
var extracted_times = dataObj.map(o => o.actual_time.split(':').slice(0, 2).map(Number));
The result would be like this:
[
[11, 0],
[13, 5]
]
So that works well.
My question:
Here is the problem I'm having. But what if I have this:
[
{
"actual_time":"11:00:00",
"length":"30"
},
{
"actual_time":"13:05:00-00:40:00",
"length":"40"
}
]
As you can see, there is a dash in the middle of two times: 13:05:00-00:40:00. How can I make it so that if there is a dash -, then do something like this:
I want the final result to be like this:
[
[11, 0],
{ from: [13, 0], to: [0, 40] }
]
how can I get it to be like that? Thanks!
var extracted_times = dataObj.map(function(obj){
// match all instances of the time string "hh:mm:ss"
var times = obj.actual_time.match(/\d\d:\d\d:\d\d/g)
// do your thing with the numbers
.map(t=>t.split(':').slice(0,2).map(Number));
// if there is only one, then return it
if(times.length == 1)
return times[0];
// if there are two, then return the object
return { from: times[0], to: times[1] };
});
Solution:
You can use a ternary expression along with your map function to iterate and determine if the String contains a (-) hyphen character by using String.prototype.includes.
--- What's a Ternary?
A ternary expression takes an expression and performs differently if true or false. It looks like this:
(expression) ? if_expression_true : if_expression_false;
The base of our ternary expression is whether or not a -(hyphen) exists in the string, so our improved syntax would look something like this:
(string.includes("-")) ? process_with_hyphen : process_without_hyphen
Code Solution:
data.map(({actual_time: s }) => s.includes("-") ?
([from, to] = s.split("-").map(p), {from,to}) :
p(s),
p = s => s.split(':').slice(0, 2).map(Number), from = to = null);
Code Explanation:
We map over our data, supplying 4 things to the map function
our function that's used with map. (Note: we use destructuring to pull actual_time from the object and store it in the variable s) This function returns one of two things.
If the - (hyphen) character is included
Split the String at the hyphen
map over the created array with the normal process
return an Object with from and to properties
The property values are [0] and [1] of the array respectively
If the - (hyphen) character is not included
perform the normal process on the String
return the resulting array
three variables
p : A function that performs our normal processing on a string and returns the Array. This is what you had in your original question.
from and to: variables we set to null. We do this because in a ternary statement you cannot make variable declarations, only variable assignments. There are multiple ways to do this, but I think this is the cleanest.
Code With Comments
//map over data and store "actual_time" in "s"
data.map(({actual_time: s }) =>
// determine if "s" includes a hyphen
s.includes("-") ?
// if it does
// split at hyphen and process the resulting array with map
// we use destructuring to assign the first and second values of the new array
// to "from" and "to"
// return a new object with "from" and "to" properties
// using the from and to variables
([from, to] = s.split("-").map(p), {from,to}) :
// if it does not
// process the String as normal
p(s),
// our declared variables for the function:
p = s => s.split(':').slice(0, 2).map(Number),
from = to = null);
Working Code Snippet:
let dataObj = [{
"actual_time": "11:00:00",
"length": "30"
},
{
"actual_time": "13:05:00-00:40:00",
"length": "40"
}
],
extract = data => data.map(({actual_time: s }) => s.includes("-") ?
([from, to] = s.split("-").map(p), {from,to}) :
p(s),
p = s => s.split(':').slice(0, 2).map(Number), from = to = null);
let extracted_times = extract(dataObj);
console.log(extracted_times);
Just check to see if the actual_time has - in it first. If not, then use your original algorithm; otherwise, split it by -, and apply the algorithm to both split pieces:
const arr = [
{
"actual_time":"11:00:00",
"length":"30"
},
{
"actual_time":"13:05:00-00:40:00",
"length":"40"
}
];
const timeToNum = time => time.split(':').slice(0, 2).map(Number);
const output = arr.map(({ actual_time }) => {
if (!actual_time.includes('-')) {
return timeToNum(actual_time);
}
const [fromTime, toTime] = actual_time.split('-');
return {
from: timeToNum(fromTime),
to: timeToNum(toTime)
};
});
console.log(output);
I suggest you extract the logic you currently have in the map into a named function and write your logic there.
Something in this spirit
function parseTime(timeString) {
if (timeString.indexOf("-") === -1) {
// no dash, return what you currently have
} else {
// dash found, split on dash and format the object
}
}
dataObj.map(parseTime)
The logic used in the if branch can probably be reused to parse from and to in the else branch, so you might want to make it a function as well.
On another note, I would rather return something like this, which should probably be easier to work with.
[
{ from: [11, 0] },
{ from: [13, 0], to: [0, 40] }
]

Convert plain text into object

I have data in unordinary format const variations
const variations = {
0: "{"productPriceLocal": "16990.00", "productId": "30028132"}",
1: "{"productPriceLocal": "22990.00", "productId": "30028233"}"
};
// this code doesn't work
// console.log(_.map(variations, 'productId'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.js"></script>
and I want this to convert to normal JS object like this, which with I can normally work
const object = {
0: {
productId: 30028132,
...
},
...
}
I tried to use lodash, doesn't work well. Does Anyone know, what I should do?
The first problem you have is that "{"productPriceLocal": "16990.00", "productId": "30028132"}" includes unescaped quotes that are terminating the string before you want it to (resulting in errors). So if you contain that string with single quotes your first problem should be fixed.
Then parsing the JSON objects as done below should produce the output you are looking for, no lodash nessecary.
const variations = {
0: '{"productPriceLocal": "16990.00", "productId": "30028132"}',
1: '{"productPriceLocal": "22990.00", "productId": "30028233"}'
};
var output = {};
for(key in variations) {
output[key] = JSON.parse(variations[key]);
}
console.log(output);
You could use Array reduce and Object.keys methods to map your object to a single object of the type you're wanting.
//Make sure you escape the quotes in your JSON strings.
const variations = {
0: "{\"productPriceLocal\": \"16990.00\", \"productId\": \"30028132\"}",
1: "{\"productPriceLocal\": \"22990.00\", \"productId\": \"30028233\"}"
};
let parsedValues = Object.keys(variations) // Get keys as an array [0,1]
.reduce((obj, key) => {
// parse to an object.
obj[key] = JSON.parse(variations[key]);
return obj;
}, {} /* initialization object */);
console.log(parsedValues);

How to parse JSON to JSON in javascript?

That so crazy, but I'm trying to convert a JSON to a JSON for any reason.I have json and i checked json at http://jsonlint.com, it's ok.
{"d": "[{\"ID\":\"VN00000123\",\"NAME\":\"JOHN GREEN\",\"GENDER\":\"Male\",\"BIRTHDAY\":\"15-10-1987\"},{\"ID\":\"VN00000456\",\"NAME\":\"MERRY BLUE\",\"GENDER\":\"Female\",\"BIRTHDAY\":\"03-12-1983\"},{\"ID\":\"VN00000789\",\"NAME\":\"BLACK BROWN\",\"GENDER\":\"Male\",\"BIRTHDAY\":\"09-07-1990\"}]"}
Now, what I need convert it like this at the following
{
"columns": [
["ID"],
["NAME"],
["GENDER"],
["BIRTHDAY"]
],
"data": [
[
"VN00000123",
"JOHN GREEN",
"Male",
"15-10-1987"
],
[
"VN00000456",
"MERRY BLUE",
"Female",
"03-12-1983"
],
[
"VN00000789",
"BLACK BROWN",
"Male",
"09-07-1990"
]
]
}
Somebody've ideas for this, share with me (using javascript or jquery). Thank you so much.
This algorithm is pretty straightforward--something like the following should work:
function parse(a) {
//create object to return
var ret = {
columns: [],
data: []
};
//iterate the source array
a.forEach(function(item, i) {
if (i === 0) {
//first time through, build the columns
for (var key in item) {
ret.columns.push(key);
}
}
//now build your data item
ret.data[i] = [];
//use the column array to guarantee that the order of the fields in the source string doesn't matter
for (var j = 0; j < ret.columns.length; j++) {
var key = ret.columns[j];
ret.data[i].push(item[key]);
}
});
return ret;
}
var j = {
"d": "[{\"ID\":\"VN00000123\",\"NAME\":\"JOHN GREEN\",\"GENDER\":\"Male\",\"BIRTHDAY\":\"15-10-1987\"},{\"NAME\":\"MERRY BLUE\",\"BIRTHDAY\":\"03-12-1983\",\"ID\":\"VN00000456\",\"GENDER\":\"Female\"},{\"GENDER\":\"Male\",\"ID\":\"VN00000789\",\"NAME\":\"BLACK BROWN\",\"BIRTHDAY\":\"09-07-1990\"}]"
};
//j is an object with one property (d) that is a JSON string that needs parsing
var o = parse(JSON.parse(j.d));
console.log(o);
You can try this example using jQuery:
https://jsfiddle.net/de02fpha/
var dump = {"d": "[{\"ID\":\"VN00000123\",\"NAME\":\"JOHN GREEN\",\"GENDER\":\"Male\",\"BIRTHDAY\":\"15-10-1987\"},{\"ID\":\"VN00000456\",\"NAME\":\"MERRY BLUE\",\"GENDER\":\"Female\",\"BIRTHDAY\":\"03-12-1983\"},{\"ID\":\"VN00000789\",\"NAME\":\"BLACK BROWN\",\"GENDER\":\"Male\",\"BIRTHDAY\":\"09-07-1990\"}]"};
var parse = function(json) {
var columns = [];
var data = [];
$.each(json, function(index, row) {
var element = [];
for (var key in row) {
if (columns.indexOf(key) == -1) columns.push(key);
element.push(row[key]);
}
data.push(element);
});
return {columns: columns, data: data};
};
var json = $.parseJSON(dump.d);
console.log(parse(json));
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
In javascript, the built in JSON class provides the two tools you need to format your JSON, no need for jquery:
JSON.parse() will handle parsing the text, and JSON.stringify can handle taking our parsed JSON and turning into a nice pretty string.
Let's slap them together.
Start with parsing and storing the JSON:
var parsedData = JSON.parse(dataToFormat);
Now to print our parsed data, we need to learn a little bit about the stringify function, specifically its space argument. Per MDN:
JSON.stringify(value[, replacer[, space]])
The space argument may be used to control spacing in the final string. If it is a number, successive levels in the stringification will each be indented by this many space characters (up to 10). If it is a string, successive levels will be indented by this string (or the first ten characters of it).
JSON.stringify({ uno: 1, dos: 2 }, null, '\t');
// returns the string:
// '{
// "uno": 1,
// "dos": 2
// }'
Note that the above code sample uses the tab character, but as described in the doc you can simply insert a number and it will use that number of spaces instead.
Alright let's print
var prettyData = JSON.stringify(parsedData, null, '\t');
prettyData should now contain a neatly formatted and indented string.
You can throw this into one line if you'd like:
var prettyData = JSON.stringify(JSON.parse(dataToFormat),null,'\t');
Now, if you wanted to add a key or something to the very top of the JSON object, you could simply define some kind of key object and attach it to the object you pass in to JSON.stringify. JSON.parse gives you a standard object, so modify it like you would any other.

JavaScript: Push to Array with unknown key names

I have a small program that returns JSON which I'm then interrogating before pushing it into an array.
An example of the data is as follows:
id=1|owner=Vina San Pedro|brandName=1865 Chilean Wine|variantName=1865 Chilean Wine|quality=Standard|minorRegionName=Nordic Countries|vol02=0|vol07=0|vol08=4.25|vol09=4.25|vol10=0|
I can iterate the above string, pushing the values into the array, but how can I 'name' the key in the array based on the field name from JSON, considering that items such as "Vol02", "Vol07" may be marked as "val02", "val07", or "minorRegionName" can in some cases by "majorRegionName".
edit
var finalSplit = brandDataRow.split('|');
$.each(finalSplit, function (x, y) {
var v = y.split('=');
$.each(v, function (m, n) {
formattedBrandData.push({ m: m }, { n: n });
});
});
In the above example, if my | delimiterred string contains "Owner=??????|Value=????????|Brand=???????" then when I push this into an array, I want the keys to be "Owner", "Value" and "Brand".
BUT, I don't know the key names until after I've returned the data, so sometimes the | delimitered string could be "Owner=??????|Line=???????|Region=??????"
Try this:
var data = "id=1|owner=Vina San Pedro|brandName=1865 Chilean Wine|variantName=1865 Chilean Wine|quality=Standard|minorRegionName=Nordic Countries|vol02=0|vol07=0|vol08=4.25|vol09=4.25|vol10=0|";
var keyVal = data.split("|");
var res = {};
for(var i =0; i< keyVal.length; i++) {
var tmp = keyVal[i].split("=")
res[tmp[0]] = tmp[1];
}
console.log(res);
Yes, it will return an object, but array can contain only numerical indexes. And in most cases you can work with object the same way as with array. Besides, see no reason to use $.each for such a simple task. Just an additional code to execute.
JSFiddle demo - see console output
First off: you're not looking for an array, but an object. JS Arrays are actually objects in drag, but that's not the point; JS doesn't have associative arrays, only objects. But to answer your question: IMO, the easiest (and, I suspect, quickest) way you can convert your string to an object is by converting it to valid JSON:
var str = 'id=1|owner=Vina San Pedro|brandName=1865 Chilean Wine|variantName=1865 Chilean Wine|quality=Standard|minorRegionName=Nordic Countries|vol02=0|vol07=0|vol08=4.25|vol09=4.25|vol10=0|';
var obj = JSON.parse('{"'+str.substring(0,str.length-1).replace(/(=|\|)/g,function(s1,s2)
{
return '"'+(s2 === '=' ? ':' : ',')+'"';
})+'"}');
This is the dense version, if we break it down:
str.substring(0,str.length-1);//leave out trailing pipe (|)
//if the pipe is not always there:
str = str.substr(-1) === '|' ? str.substring(0,str.length-1) : str;
Then replace all = and |:
str = str.replace(/(=|\|)/g,function(s1,s2)
{//s1 will be the entire matched substring, s2 the first group, not required in this case, but just so you know
return '"'+(s2 === '=' ? ':' : ',') + '"';
});//pipes become comma's, = becomes colon
We're almost there now, the returned string will be id":"1","owner":"Vina San Pedro","brandName":"1865 Chilean Wine","variantName":"1865 Chilean Wine","quality":"Standard","minorRegionName":"Nordic Countries","vol02":"0","vol07":"0","vol08":"4.25","vol09":"4.25","vol10":"0. As you can see, all we need to add are the opening and closing curly's, and a double quote at the beginning and end of the string, and we end up with valid JSON:
var obj = JSON.parse('{"'+str+'"}');//returns object
//is the same as:
obj = { brandName: "1865 Chilean Wine",
id: "1",
minorRegionName: "Nordic Countries",
owner: "Vina San Pedro",
quality: "Standard",
variantName: "1865 Chilean Wine",
vol02: "0",
vol07: "0",
vol08: "4.25",
vol09: "4.25",
vol10: "0"};
From then on:
console.log(obj.id);//logs 1
console.log(obj.owner);//logs 'Vina San Pedro'
console.log(obj['brandName']);//string access: logs "1865 Chilean Wine"
//etc...
This code is tested and working
You can use string to name the key.
Eg.
var sample = new Array();
sample["bob"] = 123;
sample.bob; //returns 123
Hope it helps.

Categories

Resources