Generating a JSON data structure using Google Spreadsheets

My current project involves learning AppScript through the use of Google Sheets as a practical example. I am attempting to generate a simple JSON object using data stored in the Sheet.

Table Example

[
  {
    "Name": "ABC",
    "ID": "123",
    "Price": 100,
    "Qty": 1
  },
  {
    "Name": "DEF",
    "ID": "342",
    "Price": 56,
    "Qty": 2
  },
  {
    "Name": "HIJ",
    "ID": "233",
    "Price": 90,
    "Qty": 3
  },
  {
    "Name": "IJK",
    "ID": "213",
    "Price": 68,
    "Qty": 5
  }
]

To achieve this, I initially followed a Youtube tutorial (https://www.youtube.com/watch?v=TQzPIVJf6-w) which focused on creating each column header as an object. However, my goal is to have the column name serve as the key and the row value as the value.

Here is the AppScript code I have been working on:

function doGet() {
  var result={};
  var rewards = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Sheet1')
  .getDataRange()
  .getValues();

  result.rewardObj = makeObject(rewards);
  //Logger.log(result.rewardObj);
  return ContentService.createTextOutput(JSON.stringify(result))
  .setMimeType(ContentService.MimeType.JSON)


}

function makeObject(multiArray)
{
  var obj = {}; 
  var colNames = multiArray.shift();
  var rowNames = multiArray.slice(0,1);
  var rowCount = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Sheet1').getLastRow();
  var colCount = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Sheet1').getLastColumn();

  for(var j=0;j<4;j++)
  {
    for(var i=0;i<4;i++)
      {
        //obj[colNames] = rowNames.map(function(item){return item[i];});
        obj[colNames[j][i]] = multiArray[j][i];
      }
  }
  Logger.log(rowCount)
  Logger.log(colCount)
  Logger.log(multiArray[57][12]);
  return obj;
}

The current output is a single object:

{"rewardObj":{"Name":"ABC","ID":"123","Price":"100","Qty":"1"}}

Disclaimer: I do not have a background in programming and I am learning scripting in a somewhat unconventional manner. Please excuse any lack of basic knowledge on my part :)

Answer №1

Give this a try:

function createJsonObjectArray(data){
    var obj = {};
    var result = [];
    var headers = data[0];
    var cols = headers.length;
    var row = [];

    for (var i = 1, l = data.length; i < l; i++){
        // get a row to fill the object
        row = data[i];

        // clear object
        obj = {};

        for (var col = 0; col < cols; col++) {
            // fill object with new values
            obj[headers[col]] = row[col];    
        }

        // add object to final result
        result.push(obj);  
    }

    return result;
}

Test function:

function test_createJsonObjectArray(){
    var data =   
        [
          ['Planet', 'Mainland', 'Country', 'City'],
          ['Earth', 'Europe', 'Britain', 'London'],
          ['Earth', 'Europe', 'Britain', 'Manchester'],
          ['Earth', 'Europe', 'Britain', 'Liverpool'],
          ['Earth', 'Europe', 'France', 'Paris'],
          ['Earth', 'Europe', 'France', 'Lion']
        ];

    Logger.log(createJsonObjectArray(data));

    // => [{Mainland=Europe, Country=Britain, Planet=Earth, City=London}, {Mainland=Europe, Country=Britain, Planet=Earth, City=Manchester}, {Mainland=Europe, Country=Britain, Planet=Earth, City=Liverpool}, {Mainland=Europe, Country=France, Planet=Earth, City=Paris}, {Mainland=Europe, Country=France, Planet=Earth, City=Lion}]
}

Answer №2

It has been some time since I last shared a solution, but here is a more adaptable approach that I have devised. I have crafted a function aptly named to transform spreadsheet data into objects by providing a list of headers and rows.

function convertToObjects(headers, rows)
{
  return rows.reduce((ctx, row) => {
    ctx.objects.push(ctx.headers.reduce((item, header, index) => {
      item[header] = row[index];
      return item;
    }, {}));
    return ctx;
  }, { objects: [], headers}).objects;
}

You can utilize the function above in this manner:

var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('YourSheetName');
var [headers, ...rows] = sheet.getDataRange().getValues();
var objects = convertToObjects(headers, rows);

If you wish to skip the first row and extract headers from the second row (as I often do), you may opt for this alternative approach:

var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('YourSheetName');
var [_, headers, ...rows] = sheet.getDataRange().getValues();
var objects = convertToObjects(headers, rows);

If you have any suggestions for enhancements to this method, feel free to share them in the feedback section below.

Answer №3

update 2022: Customize Column and Row Headers

yourJsonName col1 col2 col3 col4
row1 1 2 3
row2 4 6 4
row3 7 8 9 8

explore

function myJson() {
  var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('YourSheetName');
  var [headers, ...rows] = sheet.getDataRange().getValues();
  var jsonString = `var ${sheet.getRange(1,1).getValue()} = ${JSON.stringify(data2json(headers, rows))}`
  Logger.log (jsonString)
}
function data2json(headers, rows) {
  var obj = {},items = {};
  for (var i in rows) {
    obj = {};
    for (var col = 1; col < headers.length; col++) {
      if(rows[i][col]!='') obj[headers[col]] = rows[i][col];
    }
    items[rows[i][0]] = obj
  }
  return items;
}

var [headers, ...rows] = [['yourJsonName', 'col1', 'col2', 'col3', 'col4'], ['row1', 1.0, 2.0, 3.0, ], ['row2', 4.0, , 6.0, 4.0], ['row3', 7.0, 8.0, 9.0, 8.0]]
console.log (`var ${headers[0]} = ${JSON.stringify(data2json(headers, rows))}`)
function data2json(headers, rows) {
  var obj = {},items = {};
  for (var i in rows) {
    obj = {};
    for (var col = 1; col < headers.length; col++) {
      if(rows[i][col]!='') obj[headers[col]] = rows[i][col];
    }
    items[rows[i][0]] = obj
  }
  return items;
}

while storing in drive...adjust names accordingly (YourSheetName, YourFolderName, YourFileName)

function myJson() {
  var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('YourSheetName');
  var [headers, ...rows] = sheet.getDataRange().getValues();
  var jsonString = `var ${sheet.getRange(1,1).getValue()} = ${JSON.stringify(data2json(headers, rows))}`
  var folders = DriveApp.getFoldersByName('YourFolderName');
  if (folders.hasNext()) {
    var folder = folders.next();
    saveData(folder, 'YourFileName.json',jsonString);
  }
}
function data2json(headers, rows) {
  var obj = {},items = {};
  for (var i in rows) {
    obj = {};
    for (var col = 1; col < headers.length; col++) {
      if(rows[i][col]!='') obj[headers[col]] = rows[i][col];
    }
    items[rows[i][0]] = obj
  }
  return items;
}
function saveData(folder, fileName, content) {
  var children = folder.getFilesByName(fileName);
  var file = null;
  if (children.hasNext()) {
    file = children.next();
    file.setContent(content);
  } else {
    file = folder.createFile(fileName, content);
  }
  Logger.log(file.getUrl())
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

How to fetch JSON data in React using HTTP requests

Entering the world of React technology as a beginner. I am wondering, how can I retrieve JSON data from an HTTP request? Referencing https://i.sstatic.net/MbX4i.png, I am able to successfully log the value of console.log(dataExt); from within the functio ...

A function that creates a new object with identical keys as the original input object

I am working on creating a function fn() that has the following specifications: It takes a single argument x which is an object with optional keys "a" and "b" (each field may be numeric for simplicity) The function should return a new object with the same ...

Is it feasible to incorporate an external library as a script within a class or functional component in React?

Welcome and thank you for taking the time to read this question! I am currently working on a project where I need to load a TIFF image. After researching, I found a library that can help with this task: https://github.com/seikichi/tiff.js There is also ...

Menu is not functioning properly as it is not staying fixed in place

I am trying to create a fixed menu that sticks to the browser window as it scrolls. However, I am encountering an issue where the transition from sticky to fixed is not smooth when I remove position: relative; from navbar__box. window.onscroll = functio ...

The input data that was submitted is not appearing on the confirmation page

While working on a stepper form, I encountered an issue where users entered data and clicked the next button to navigate through multiple steps until reaching the confirmation page. If the user was not logged in, they were redirected to the login page. Af ...

next-pwa seems to be malfunctioning without any discernible errors in the production environment

The repository is publicly available // next.config.js const withPWA = require("next-pwa"); module.exports = withPWA({ pwa: { dest: "public", sw: '/sw.js' }, }); _document.js _app.js Live I have verified the fu ...

Pattern matching for updating JSON string

Can anyone help me with a regular expression to replace matching strings with empty values? Here is the JSON data I am working with: {"session":{"convener_id":null,"convergence":false,"created_at":"2012-06-02T10:00:00","event_id":null,"id":42,"name":"Tes ...

AngularJS is restricting the use of square brackets within the URL parameter, specifically the character '[.'

My goal is to connect to an external API Everything works smoothly when my parameters are set up like this $http.post('http://api.myprivatebox.com/users.json', { email : email, password : password}).then(function (results) { console.log( ...

The IMDB API is throwing a GraphQL error that says, "ClientError: Unable to retrieve information on the field 'Image' for the type 'MainSearchEntity'."

Seeking suggestions for the top 10 movies related to 'Africa' using the IMDB API demo available here. In my query, I am looking for movie id, title, poster image, and filming location. However, I encounter an error message 'ClientError: Ca ...

Cause a JavaScript error to occur if geolocation services are disabled

I have an AngularJS project where I am utilizing the following code snippet to fetch a device's GPS coordinates: // when user clicks on geo button $scope.getGeoLocation = function() { var geocoder = new google.maps.Geocoder(); window.navigato ...

Having trouble retrieving the toDataURL data from a dynamically loaded image source on the canvas

Currently, I am working on a project that involves a ul containing li elements with images sourced locally from the "/images" folder in the main directory. <section class="main"> <ul id="st-stack" class="st-stack-raw"> ...

The feature of determining if an edge exists, within the dagre-d3/graphlib,

Has anyone utilized the graph.hasEdge function in dagre-d3/graphlib to check for the existence of an edge between two nodes? This API takes two arguments representing the two nodes and verifies if there is an edge connecting them. I am facing an issue whe ...

Can we determine if scrollIntoView is compatible with different browsers through testing?

I am searching for a method to conduct a real-time assessment of the scrollIntoView feature in my user's browser. This is not a simple "caniuse" check; instead, I want to implement graceful degradation. I am utilizing jQuery and would prefer to utiliz ...

Saving the chosen outcome to a collection for easy export in JSON format

I've developed an Angular application that interacts with the Spotify API for searching purposes. The search results are displayed and users can add their selected choices to a list on the right by clicking on a + sign. Currently, I am able to perform ...

Incorporate an external JavaScript script using code

I'm currently working on integrating a map widget from 'Awesome Table' into the codebase of an open-source CRM platform. The specific code snippet I need to add is <div data-type="AwesomeTableView" data-viewID="-KLtnY5OHJPgnEOX1bKf"> ...

When setting AngularJS $locationProvider.html5Mode(true), an error occurs stating `url is undefined`

I've been experimenting with html5Mode for AngularJS URLs and encountered an issue. The following code functions as expected: .config(["$routeProvider", "$locationProvider", function($routeProvider, $locationProvider){ $routeProvider.whe ...

Gradually reveal the background image as the page loads

Is there a way to add a fadeIn effect to the random background image loading using jQuery? Currently, the script I am using displays a random background on refresh without the desired transition effect. How can I achieve the fadeIn effect when the image ...

Tips for obtaining Array elements within a JSON object utilizing handlebars

var express = require('express'); var router = express.Router(); var data = { products :{ name:'Computers', price:'500' }, items:[ {name: 'Keyboard' , cost:'50'}, {name: 'M ...

Preventing Event Bubbling in Polymer 1.5 for iOS When Using iron-pages

Our single-page app utilizes iron pages and express-router for navigation. While it functions flawlessly on browsers and Android devices, we've encountered a bug when using iOS. The issue arises when switching pages by clicking a button. If the button ...

The type '{}' cannot be assigned to type 'IntrinsicAttributes & FieldsProp'. This error message is unclear and difficult to understand

"The error message "Type '{}' is not assignable to type 'IntrinsicAttributes & FieldsProp'.ts(2322)" is difficult to understand. When I encountered this typeerror" import { useState } from "react"; import { Card } fr ...