Creating a nested JSON object with Google Sheets - javascript

I am trying to teach myself some AppScript/Javascript. As an exercise, I am want to generate the following JSON object
[
{
"config_type": "City Details",
"config_data": [
{
"city_type": "MAJOR_CITY",
"city_data": [
{
"city_name": "BIGFOOLA",
"monetary_data": [
{
"currency_data": [
{
"dollars": 1000
}
]
}
]
}
]
}
]
}
]
I want to be able to enter only few details like "City Details", "MAJOR_CITY", and the dollar value - 1000 in a Google Sheet. The script should be able to generate the above JSON.
So I started by creating the names of all the Arrays and Objects in one row. In front of the the arrays, there was a blank cell and in front of the object the value. The Sheet looks like this
A B
config_type City Details
config_data
city_type MAJOR_CITY
city_data
city_name BIGFOOLA
monetary_data
currency_data
dollars 1000
I am able to get all of the details in a single object, but struggling to nest them under each other. How do I go about this?
Edit :Here is what I have for now
function doGet(){
var result={}
var rewardSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("CITY")
var reward_data = rewardSheet.getRange("A1:B13").getValues();
result = getJsonArrayFromData(reward_data);
return ContentService.createTextOutput(JSON.stringify(result))
.setMimeType(ContentService.MimeType.JSON)
}
function getJsonArrayFromData(data)
{
var column_headers = data[0];
var col_len = column_headers.length;
var row = [];
var reward_obj = [];
var config_obj = {};
var config_type = {};
var config_data = [];
var reward_type = {};
var reward_data = [];
var reward_name = {};
var reward_data_2 = [];
var currency_data = [];
var curreny_obj = {};
var rewardSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("CITY")
var row_items = rewardSheet.getRange(1,1,data.length,1).getValues();
//Logger.log(row_items);
for(var i=0;i<data.length;i++){
row = data [i];
config_type ={};
reward_type[config_type]={};
reward_name[reward_type]={};
//Logger.log(row);
for(var r=0;r<row.length;r++)
{
config_type[row[r]] = row[r+1];
reward_type[row[r]] = row[r+1];
reward_name[row[r]] = row[r+1];
}
config_data.push(config_type,reward_type,reward_name);
//reward_data.push(reward_name);
reward_obj = config_data;
}
Logger.log(reward_obj);
return reward_obj;
}
Ps: I know the JSON is messy, but its just to understand and teach myself.

You hard-coded a bunch of property names as variables; this is not a good approach.
Here is how one can do this. The variable output holds the object we'll return at the end, while currentObject points to the object that is due to be filled next. When it comes to filling it, we either have a scalar value data[i][1] to put in, or we don't, in which case a new object is created and becomes the new currentObject.
function formJSON() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("CITY");
var data = sheet.getDataRange().getValues();
var currentObject = {};
var output = [currentObject]; // or just currentObject
for (var i = 0; i < data.length; i++) {
if (data[i][1]) {
currentObject[data[i][0]] = data[i][1];
}
else {
var newObject = {};
currentObject[data[i][0]] = [newObject]; // or just newObject
currentObject = newObject;
}
}
Logger.log(JSON.stringify(output));
}
The output is
[{"config_type":"City Details","config_data":[{"city_type":"MAJOR_CITY","city_data":[{"city_name":"BIGFOOLA","monetary_data":[{"currency_data":[{"dollars":1000}]}]}]}]}]
or, in beautified form,
[{
"config_type": "City Details",
"config_data": [{
"city_type": "MAJOR_CITY",
"city_data": [{
"city_name": "BIGFOOLA",
"monetary_data": [{
"currency_data": [{
"dollars": 1000
}]
}]
}]
}]
}]
Incidentally, I don't see why you wanted to put every object in an array. A property can be another object. Removing square brackets on the commented lines we would get
{
"config_type": "City Details",
"config_data": {
"city_type": "MAJOR_CITY",
"city_data": {
"city_name": "BIGFOOLA",
"monetary_data": {
"currency_data": {
"dollars": 1000
}
}
}
}
}

Related

Array is null after assigning value to it

I have variable that is containing some sort of JSON data,
var blogData = [
{
"blogTitle":"Bangladesh",
"imagePath":"/img/blog/bangladesh.jpg"
},{
"blogTitle":"India",
"imagePath":"/img/blog/india.jpg"
}
]
What I want a new array titleFilter like:
var titleFilter = [
Bangladesh : "/img/blog/bangladesh.jpg",
India : "/img/blog/india.jpg"
]
So, for this purpose, I have tried this:
var titleFilter = [];
for (var i = 0; i < blogData.length; i++) {
titleFilter[blogData[i].blogTitle] = blogData[i].imagePath;
}
The problem is, I am getting the titleFilter array as:
var titleFilter = [
Bangladesh : "",
India : ""
]
It would be great if someone help me regarding this problem.
Try this:
const blogData = [
{
"blogTitle":"Bangladesh",
"imagePath":"/img/blog/bangladesh.jpg"
},{
"blogTitle":"India",
"imagePath":"/img/blog/india.jpg"
}
];
const result = blogData.reduce((acc, ele)=> (acc[ele.blogTitle] = ele.imagePath , acc),{});
console.log(result);
I am not sure what you are looking for but you can use map like this to achieve it.
var map = new Object(); // or var map = {};
map[blogData[i].blogTitle] = blogData[i].imagePath;
var blogData = [
{
"blogTitle":"Bangladesh",
"imagePath":"/img/blog/bangladesh.jpg"
},
{
"blogTitle":"India",
"imagePath":"/img/blog/india.jpg"
}
]
var titleFilter = {}
blogData.forEach( x => titleFilter[x.blogTitle] = x.imagePath )
Use this code, and you will get the desired result in titleFilter

Flat array to multi dimensional array (JavaScript)

I have the following array:
var sampleArray = [
"CONTAINER",
"BODY",
"NEWS",
"TITLE"];
I want to have the following output:
var desiredOutput = [{
"CONTAINER": [{
"BODY": [{
"NEWS": [{
"TITLE": []
}]
}]
}]
}];
How can I achieve this in JavaScript?
Already tried with recursive loop, but it does not work, gives me undefined.
dataChange(sampleArray);
function dataChange(data) {
for (var i = 0; i < data.length; i++) {
changeTheArray[data[i]] = data[i + 1];
data.splice(i, 1);
dataChange(changeTheArray[data[i]]);
}
}
Thanks
This does what you're asking for, in one line, and with no additional variables:
let desiredOutput = sampleArray.reduceRight((obj, key) => [ { [key]: obj } ], []);
The reduceRight call, starting from the right hand end of the array, progressively accumulates the current data (seeded with the initial value of []) as the value of the single key in a new object { [key] : _value_ } where that object is itself the single entry in an array [ ... ].
This will do it:
const sampleArray = ["CONTAINER", "BODY", "NEWS", "TITLE"];
const data = []; // Starting element.
let current = data; // Pointer to the current element in the loop
sampleArray.forEach(key => { // For every entry, named `key` in `sampleArray`,
const next = []; // New array
current.push({[key]: next}); // Add `{key: []}` to the current array,
current = next; // Move the pointer to the array we just added.
});
console.log(data);
{[key]: next} is relatively new syntax. They're computed property names.
This:
const a = 'foo';
const b = {[a]: 'bar'};
Is similar to:
const a = 'foo';
const b = {};
b[a] = 'bar';
You could re-write the forEach as a one-liner:
const sampleArray = ["CONTAINER", "BODY", "NEWS", "TITLE"];
const data = []; // Starting element.
let current = data; // Pointer to the current element in the loop
sampleArray.forEach(key => current.push({[key]: current = [] }));
console.log(data);
This current.push works a little counter-intuitively:
Construct a new element to push. This assigns a new value to current.
Push the new element to the reference .push was called on.
That reference is the value of current before current = [].
Hi i made a little demo :
var sampleArray = [
"CONTAINER",
"BODY",
"NEWS",
"TITLE"
],
generateArray = [],
tmp = null;
for(var i = 0; i < sampleArray.length; i++) {
if(tmp===null){
generateArray[sampleArray[i]] = {};
tmp = generateArray[sampleArray[i]];
}else{
tmp[sampleArray[i]] = {};
tmp = tmp[sampleArray[i]];
}
}
console.log(generateArray);

array object manipulation to create new object

var actual = [
{"country":"UK","month":"JAN","SR":"John P","AC":"24","PR":"2","TR":1240},
{"country":"AUSTRIA","month":"JAN","SR":"Brad P","AC":"64","PR":"12","TR":1700},
{"country":"ITALY","month":"JAN","SR":"Gim P","AC":"21","PR":"5","TR":900},
{"country":"UK","month":"FEB","SR":"John P","AC":"14","PR":"4","TR":540},
{"country":"AUSTRIA","month":"FEB","SR":"Brad P","AC":"24","PR":"12","TR":1700},
{"country":"ITALY","month":"FEB","SR":"Gim P","AC":"22","PR":"3","TR":600},
{"country":"UK","month":"MAR","SR":"John P","AC":"56","PR":"2","TR":1440},
{"country":"AUSTRIA","month":"MAR","SR":"Brad P","AC":"24","PR":"12","TR":700},
{"country":"ITALY","month":"MAR","SR":"Gim P","AC":"51","PR":"5","TR":200}
];
var expect = [
{month:"JAN",val: {"UK":"24","AUSTRIA":"64","ITALY":"21"}},
{month:"FEB",val: {"UK":"14","AUSTRIA":"24","ITALY":"22"}},
{month:"MAR",val: {"UK":"56","AUSTRIA":"24","ITALY":"51"}}
];
I have array of objects which i need to reshape for one other work. need some manipulation which will convert by one function. I have created plunker https://jsbin.com/himawakaju/edit?html,js,console,output
Main factors are Month, Country and its "AC" value.
Loop through, make an object and than loop through to make your array
var actual = [
{"country":"UK","month":"JAN","SR":"John P","AC":"24","PR":"2","TR":1240},
{"country":"AUSTRIA","month":"JAN","SR":"Brad P","AC":"64","PR":"12","TR":1700},
{"country":"ITALY","month":"JAN","SR":"Gim P","AC":"21","PR":"5","TR":900},
{"country":"UK","month":"FEB","SR":"John P","AC":"14","PR":"4","TR":540},
{"country":"AUSTRIA","month":"FEB","SR":"Brad P","AC":"24","PR":"12","TR":1700},
{"country":"ITALY","month":"FEB","SR":"Gim P","AC":"22","PR":"3","TR":600},
{"country":"UK","month":"MAR","SR":"John P","AC":"56","PR":"2","TR":1440},
{"country":"AUSTRIA","month":"MAR","SR":"Brad P","AC":"24","PR":"12","TR":700},
{"country":"ITALY","month":"MAR","SR":"Gim P","AC":"51","PR":"5","TR":200}
];
var outTemp = {};
actual.forEach(function(obj){ //loop through array
//see if we saw the month already, if not create it
if(!outTemp[obj.month]) outTemp[obj.month] = { month : obj.month, val: {} };
outTemp[obj.month].val[obj.country] = obj.AC; //add the country with value
});
var expected = []; //convert the object to the array format that was expected
for (var p in outTemp) {
expected.push(outTemp[p]);
}
console.log(expected);
Iterate through array and create new list
var actual = [
{"country":"UK","month":"JAN","SR":"John P","AC":"24","PR":"2","TR":1240},
{"country":"AUSTRIA","month":"JAN","SR":"Brad P","AC":"64","PR":"12","TR":1700},
{"country":"ITALY","month":"JAN","SR":"Gim P","AC":"21","PR":"5","TR":900},
{"country":"UK","month":"FEB","SR":"John P","AC":"14","PR":"4","TR":540},
{"country":"AUSTRIA","month":"FEB","SR":"Brad P","AC":"24","PR":"12","TR":1700},
{"country":"ITALY","month":"FEB","SR":"Gim P","AC":"22","PR":"3","TR":600},
{"country":"UK","month":"MAR","SR":"John P","AC":"56","PR":"2","TR":1440},
{"country":"AUSTRIA","month":"MAR","SR":"Brad P","AC":"24","PR":"12","TR":700},
{"country":"ITALY","month":"MAR","SR":"Gim P","AC":"51","PR":"5","TR":200}
];
var newList =[], val;
for(var i=0; i < actual.length; i+=3){
val = {};
val[actual[i].country] = actual[i]["AC"];
val[actual[i+1].country] = actual[i+1]["AC"];
val[actual[i+2].country] = actual[i+2]["AC"];
newList.push({month: actual[i].month, val:val})
}
document.body.innerHTML = JSON.stringify(newList);
This is the correct code... as above solution will help you if there are 3 rows and these will be in same sequnece.
Here is perfect solution :
var actual = [
{"country":"UK","month":"JAN","SR":"John P","AC":"24","PR":"2","TR":1240},
{"country":"AUSTRIA","month":"JAN","SR":"Brad P","AC":"64","PR":"12","TR":1700},
{"country":"ITALY","month":"JAN","SR":"Gim P","AC":"21","PR":"5","TR":900},
{"country":"UK","month":"FEB","SR":"John P","AC":"14","PR":"4","TR":540},
{"country":"AUSTRIA","month":"FEB","SR":"Brad P","AC":"24","PR":"12","TR":1700},
{"country":"ITALY","month":"FEB","SR":"Gim P","AC":"22","PR":"3","TR":600},
{"country":"UK","month":"MAR","SR":"John P","AC":"56","PR":"2","TR":1440},
{"country":"AUSTRIA","month":"MAR","SR":"Brad P","AC":"24","PR":"12","TR":700},
{"country":"ITALY","month":"MAR","SR":"Gim P","AC":"51","PR":"5","TR":200}
];
var tmpArray = [];
var obj =[];
for(var k=0; k<actual.length; k++){
var position = tmpArray.indexOf(actual[k].month);
if(position == -1){
tmpArray.push(actual[k].month);
val = {};
for(var i=0; i<actual.length; i++){
if(actual[i].month == actual[k].month){
val[actual[i].country] = actual[i]["AC"];
}
}
obj.push({month: actual[k].month, val:val});
}
}

Setting up a variable length two-dimensional array

I have a string as follows :
Panther^Pink,Green,Yellow|Dog^Hot,Top
This string means I have 2 main blocks(separated by a '|') :
"Panther" and "Dog"
Under these two main blocks, I have, lets say "subcategories".
I wanted to create a 2-dimensional array represented (in logic) as follows :
Panther(Array 1) => Pink(Element 1),Green(Element 2), Yellow(Element 3)
Dog(Array 2) => Hot(Element 1), Top(Element 2)
Also,I want to be able to add a main block, lets say "Cat" with possible categories "Cute,Proud" to the two dimensional array
I've managed to get an Array containing "Panther^Pink,Green,Yellow" and "Dog^Hot,Top" by using JavaScript's split function.
Note that this string is received via Ajax and can be of any length, though the format shown above is always used.
----------------------------- EDIT ----------------------------
Ok, my script so far is :
$(document).ready(function(){
appFunc.setNoOfAppBlock('Panther^Pink,Green,Yellow|Dog^Hot,Top');
appFunc.alertPing();
});
var appFunc = (function(stringWithSeper) {
var result = {},
i,
categories = new Array(),
subcategories;
return {
setNoOfAppBlock: function(stringWithSeper){
categories = stringWithSeper.split("|");
for (i = 0; i < categories.length; i++) {
subcategories = categories[i].split("^");
result[subcategories[0]] = subcategories[1].split(",");
}
},
alertPing: function(){
alert(result["Panther"][1]);
}
};
})();
However, the function "alertPing" isn't "alerting" anything.What am am I doing wrong ?
To me the most logical representation of your data:
Panther^Pink,Green,Yellow|Dog^Hot,Top
Is with a JavaScript object with a property for each category, each of which is an array with the subcategories:
var data = {
Panther : ["Pink", "Green", "Yellow"],
Dog : ["Hot", "Top"]
}
You would then access that by saying, e.g., data["Dog"][1] (gives "Top").
If that format is acceptable to you then you could parse it as follows:
function parseData(data) {
var result = {},
i,
categories = data.split("|"),
subcategories;
for (i = 0; i < categories.length; i++) {
subcategories = categories[i].split("^");
result[subcategories[0]] = subcategories[1].split(",");
}
return result;
}
var str = "Panther^Pink,Green,Yellow|Dog^Hot,Top";
var data = parseData(str);
Assuming you're trying to parse your data into something like this:
var result = {
Panther: ["Pink", "Green", "Yellow"],
Dog: ["Hot", "Top"]
}
you can use string.split() to break up your string into subarrays:
var str = "Panther^Pink,Green,Yellow|Dog^Hot,Top";
var result = {}, temp;
var blocks = str.split("|");
for (var i = 0; i < blocks.length; i++) {
temp = blocks[i].split("^");
result[temp[0]] = temp[1].split(",");
}
Data can then be added to that data structure like this:
result["Cat"] = ["Cute", "Proud"];
Data can be read from that data structure like this:
var dogItems = result["Dog"]; // gives you an array ["Hot", "Top"]
You can use something like:
function parseInput(_input) {
var output = [];
var parts = _input.split('|');
var part;
for(var i=0; i<parts.length; i++) {
part = parts[i].split('^');
output[part[0]] = part[1].split(',');
}
return output;
}
Calling parseInput('Panther^Pink,Green,Yellow|Dog^Hot,Top'); will return:
output [
"Panther" => [ "Pink", "Green", "Yellow" ],
"Dog" => [ "Hot", "Top" ]
]
To add another item to the list, you can use:
output["Cat"] = ["Cute", "Proud"];

Coverting json array to js objects

I have a json string like this
[ {
"name":"sourabh",
"userid":"soruabhbajaj",
"id":"11",
"has_profile_image":"0" },
{
"name":"sourabh",
"userid":"sourabhbajaj",
"id":"12",
"has_profile_image":"0"
}]
Now, I want to convert this json array to the string like this so that I can access any object using its id on the entire page.
{ "11": {
"name":"sourabh",
"userid":"soruabhbajaj",
"id":"11",
"has_profile_image":"0" },
"12": {
"name":"sourabh",
"userid":"sourabhbajaj",
"id":"12",
"has_profile_image":"0"
}}
Suggest some code please. Thanx in advance
EDIT:
Will this work:
user.(function(){return id;})
And then accessing objects like this
user.id.name
I mean is this a correct way of defining object?
var data = ... the initial array
var result = {};
for (var i = 0; i < data.length; i++) {
var element = data[i];
result[element.id] = element;
};
var data = [
{"name":"sourabh", "userid":"soruabhbajaj", "id":"11", "has_profile_image":"0"},
{"name":"sourabh", "userid":"sourabhbajaj", "id":"12", "has_profile_image":"0"}
];
var newData = {};
for (var i = 0; i < data.length; i++) {
var item = data[i];
newData[item.id] = item;
}
Now newData is an object where the keys are the ids of the people and the data for each key is the person object itself. So, you can access an item like this:
var id = "11";
var name = newData[id].name;

Categories

Resources