A guide to reading a JSON object with nested arrays using Google Apps Script

I'm facing a challenge in parsing a JSON string with nested arrays. To illustrate, here's an example of the JSON

var json = {
"id": "123456", 
"cost_name":"john", 
"line_item":[{
"item_name":"table", "quantity":"1", "properties":[{
"color":"black", "style":"rustic"
}]},
{
"item_name":"chair", "quantity":"3", "properties":[{
"color":"white", "style":"modern"
}]}],
"address":"123_street"
 }

My goal is to extract the item_name and quantity for each line_item, along with their respective color and style.

The JSON data comes from a webhook, meaning the order can vary.

ADDED CONTEXT: (@Taineke's request)

I'm attempting to write this data to a Google Sheet using Apps Script, here's my code:

function doPost(e) {
  var ss = SpreadsheetApp.getActiveSheet();
  var data = JSON.parse(e.postData.contents);
  
//extract data here
var I= item_name;
var Q = quantity;
var C = color;
var S = style;
  
  ss.appendRow([I,Q,C,S])
}

HERE IS UPDATED e.postData.contents (that @Tanaike) requested from a test webhook

{ID:3175309607101,email:"email@example.com",...}

HERE IS MY LATEST CODE. It works but maybe can be cleaner and faster. which I'm having issues with Shopify's 5 second wait time to refiring if no response is received.

function doPost(e){
  var data = JSON.parse(e.postData.contents);
  var ss = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Sheet1');
 
  var l = data.line_items.length; 
 
  for (var i=0;i<l;i++){
  var prop = data.line_items[i].properties;

  if (prop.length>0){
  var pdf = prop.find(function(x) {if(x.name == "_pdf") return x});
  if (!pdf){pdf = "Prop not found";}else{pdf = pdf.value};
  
  var shape = prop.find(function(x) {if(x.name.toLowerCase() == "shape") return x});
  if (!shape){shape = "Prop not found";}else{shape = shape.value};
  

  }else{
  var pdf = "N/A"
  var shape = "N/A"
  };


  var count = "Item "+ (i+1) + " of " + l;
  var qty = data.line_items[i].quantity;
  var title = data.line_items[i].title;
  var id = data.id.toString();
  var email = data.email;
  var totalPrice = data.total_price;
  var discounts = data.total_discounts;
  var acceptAds = data.buyer_accepts_marketing;
  var orderStatus = data.order_status_url;
  var addr = data.shipping_address.address1;
  var city = data.shipping_address.city;
  var state = data.shipping_address.province;
  var zip = data.shipping_address.zip;
  var phone = data.shipping_address.phone;
  var firstName = data.shipping_address.first_name;
  var lastName = data.shipping_address.last_name;
  var orderNum = data.name;
  var d = new Date(data.created_at).toLocaleString();
  ss.appendRow([d,orderNum,email,count,title,shape,qty,totalPrice,discounts,pdf,firstName,lastName,addr,city,state,zip,phone,orderStatus]);
  
if (pdf != "N/A"){
if (pdf != "Prop not found"){
  var res = UrlFetchApp.fetch(pdf);
  var blob = res.getBlob();
  var createFile = DriveApp.getFolderById('xxxxxxxxxxxxxxxx-').createFile(blob.getAs('application/pdf'));
  var fileName = orderNum + " " + qty;
  createFile.setName(fileName);
}}
  };
}

Answer №1

I had a hunch that in your JSON data, the equal sign (=) might be replaced with a colon (:). If this is the case, how about trying the script below?

Check out this sample script:

var json = {
  "id": 123456,
  "cost_name": "john",
  "line_item": [
    {
      "item_name": "table",
      "quantity": 1,
      "properties": [
        {
          "color": "black",
          "style": "rustic"
        }
      ]
    },
    {
      "item_name": "chair",
      "quantity": 3,
      "properties": [
        {
          "color": "white",
          "style": "modern"
        }
      ]
    }
  ],
  "address": "123_street"
};

const res = json.line_item.map(({item_name, quantity, properties: [{color, style}]}) => [item_name, quantity, color, style]);
console.log(res)

Note:

  • Unfortunately, I'm not clear on the specific format you are looking for in the result. In the provided sample script above, each value is stored in an array. If this isn't the desired output format, could you provide the expected values? I would be happy to make adjustments accordingly.

  • If needed, please ensure V8 runtime is enabled in the script editor.

Reference:

Update 1:

Based on your latest question update, it seems that 'data' represents the JSON in your initial script and you wish to append the values of 'item_name,' 'quantity,' 'color,' and 'style' to a Google Spreadsheet. Consider the following modification:

Updated script:

function doPost(e) {
  var data = JSON.parse(e.postData.contents);
  var res = data.line_item.map(({item_name, quantity, properties: [{color, style}]}) => [item_name, quantity, color, style]);
  var sheet = SpreadsheetApp.getActiveSheet();
  sheet.getRange(sheet.getLastRow() + 1, 1, res.length, res[0].length).setValues(res);
}

Note:

  • If you're using Web Apps, remember to redeploy them as a new version when modifying the script to ensure the latest version is applied. Please proceed with caution.

Update 2:

Reviewing your recent question update, it appears there are differences in the additional values compared to your original inquiry. You now aim to extract 'Shape' and '_pdf' values nested within 'properties.' Here's a revised script based on these parameters:

Sample script adaptation:

The 'data' variable in this instance pertains to your added values. Keep this in mind while implementing the script.

function doPost(e) {
  var data = JSON.parse(e.postData.contents);
  
  const checkNames = ["Shape", "_pdf"];
  const res = data.line_items.reduce((ar, {properties}) => {
    if (properties) {
      properties.forEach(({name, value}) => {
        if (checkNames.includes(name)) ar.push([name, value]);
      });
    }
    return ar;
  }, []);
  if (res.length > 0) {
    var sheet = SpreadsheetApp.getActiveSheet();
    sheet.getRange(sheet.getLastRow() + 1, 1, res.length, res[0].length).setValues(res);
  }
}
  • The script ensures 'setValues' is only executed when 'properties' values exist to prevent errors.

Note:

  • The provided script is tailored to your specific additional values. Please exercise caution if any changes occur to the value structure, as it may impact script functionality.
  • When making revisions to Web Apps scripts, remember to redeploy them as a new version to reflect the updated script. Approach this step carefully.

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

What steps can be taken to solve the JavaScript error provided below?

My objective is to create a new variable called theRightSide that points to the right side div. var theRightSide = document.getElementById("rightSide"); Once all the images are added to the leftSide div, I need to use cloneNode(true) to copy the left ...

What is the best way to temporarily bold a cell item within a table row for a specified duration of time?

I am experiencing an issue with a section of my code where I am fetching values from the server and updating a table if a certain value is not present. Once the update is made, I want to visually notify the user by temporarily making the cell's value ...

Is the "as" decorator in Next.js Link no longer functioning properly with dynamic routes?

My route is dynamic: test/[id].js When a user clicks on a link to /test/1, Next.js successfully renders the correct page. The issue arises when I try to mask the /test/1 URL with something else. <Link href="/test/1" as="/any/thing/here ...

What is the process for incorporating custom controls into the Mantine Embla Carousel within a Next.js environment?

Check out this code snippet: import React from "react"; import { Container } from "@mantine/core"; import { Carousel } from "@mantine/carousel"; import { ArticleCard } from "@/components"; import { cards } from " ...

Transmitting JSON data to another server with ASP.NET Core MVC using C#

Apologies for any language mistakes. I am looking to send JSON data to another server. For example: 127.0.0.1/api/start On this other server, I have a service that I created running, which requires receiving JSON data in the following format: {"ServerI ...

Scala: Best Practices for Parsing Multiple JSON Files in Subdirectories

I need assistance with finding a code snippet in Scala for reading multiple nested JSON files within subdirectories in Hadoop. It would be even more helpful if we could consolidate the data from these JSON files into one single file located in a different ...

Exploring the Utilization of FormData and form.serialize within the Data Parameter of Ajax Jquery

My form includes a multiupload uploader for files, structured like this : <div class="col-md-4"> <div class="form-group"> <label class="control-label col-md-3">Location</label> <div class="col-md-9"> <?php ...

What is the best way to perform the subtraction of sparse matrices?

I am currently facing an issue with array subtraction in Python: import numpy as np from scipy.sparse import csr_matrix a = np.array([[1, 2], [3, 4]]) b = a[:, None] - a[None, :] sum_ = np.sum(b, axis=-1) print(sum_) The above code works fine. However, ...

Utilizing $resource within a promise sequence to correct the deferred anti-pattern

One challenge I encountered was that when making multiple nearly simultaneous calls to a service method that retrieves a list of project types using $resource, each call generated a new request instead of utilizing the same response/promise/data. After doi ...

Creating custom CSS data-tooltip for image maps without the use of jquery

I stumbled upon the Pure CSS Tooltips (data-tooltip) feature showcased at http://www.frequency-decoder.com/demo/css-tooltips/, and I am eager to implement it on a specific area of an image map in a rectangular shape. However, despite finding a JavaScript c ...

Refresh the view when the URL is modified

Utilizing angularjs alongside ui-router (using the helper stateHelperProvider) to organize views and controllers on the page. Encountering an issue where the views are not updating as expected. The relevant code snippet config.js app.config(function($h ...

Fill in a text box with a chosen value from a linked drop-down menu

My database contains two tables: 1 - tbl_category 2 - tbl_shelf_place I am working towards displaying the shelf_code in a textbox based on the selected category_name from a drop-down (book_category) with a value of category_id, instead of using another ...

Steps to enable Nodemailer to execute a separate .js script

Currently, I have the main nodejs server file named myserver.js const express = require("express"); const app = express(); const nodemailer = require("nodemailer"); const port = 80; const vectorExpress = require("./node_modules/@ ...

Struggling to make even the most basic example work with TypeScript and npm modules

After stumbling upon this repository that made using npm modules within a Typescript program look easy, I decided to give it a try by forking it and making some changes. My goal was to add another package to get a better understanding of the process. So, I ...

Suggestions for preventing the highlighting of the space between buttons on a webpage

html: <button id='automoney' onclick='minusTen()'></button> <button id='automoney2' onclick='minusHundred()'></button> <button id='automoney3' onclick='minusFiveHundred()& ...

When text exceeds multiple lines, display an ellipsis to indicate overflow and wrap only at word boundaries

Here is an example snippet of my code: <div class="container"> <div class="item n1">Proe Schugaienz</div> <div class="item n2">Proe Schugaienz</div> </div> and I am using the following jQuery code: $(&apos ...

An effective method for displaying the total sum of selected row data in Angular dynamically

My goal is to dynamically show the sum of selected column data using the SelectionModel on the rows that I have selected in my table. The displayed data should update when I select or deselect rows. I initially believed that utilizing ngOnInit() would hel ...

Using Ajax on a WordPress webpage

I am currently experimenting with this piece of Ajax jQuery code within a WordPress page: 1. <script> 2. $(document).ready(function(){ 3. $("button").click(function(){ 4. $.ajax({ 5. method: 'GET', 6. ...

Flex box causing Bootstrap5 responsive table to overflow

Need help with fixing overflow issue in a fixed-width div used as a left sidebar. The main content renders correctly except for tables with many columns, causing overflow before the scroll bar appears. How can this be resolved? Various layout attempts hav ...

Guide to positioning the highlighted image in a lightbox gallery: Aligning the active image in the

Hey there, I have implemented the Lightbox gallery feature in my Django application. The gallery functions such that when a user clicks on an image, it opens up the gallery with the selected image displayed prominently, along with the functional icons for ...