I'm having difficulty parsing a JSON string with nested arrays. here is 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"
}
I need to get the item_name and quantity of each line_item and I also need the color and style of each
I'm receiving this JSON from a webhook so the order is never the same.
ADDED CONTEXT: (#Taineke's request)
I'm trying to write this to a google sheet with apps script here is 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":"sample#sample.com","closed_at":null,"created_at":"2021-01-05T21:35:06-05:00","updated_at":"2021-01-05T21:35:08-05:00","number":1586,"note":"","token":"3491883c672f110eaab82f8dd8080052","gateway":null,"test":false,"total_price":"0.00","subtotal_price":"0.00","total_weight":0,"total_tax":"0.00","taxes_included":false,"currency":"USD","financial_status":"paid","confirmed":true,"total_discounts":"18.00","total_line_items_price":"18.00","cart_token":"a3c9cb049e2f631a8393cf37547623e2","buyer_accepts_marketing":false,"name":"#2586","referring_site":"","landing_site":"\/","cancelled_at":null,"cancel_reason":null,"total_price_usd":"0.00","checkout_token":"11d27a9399b514cb6ba246a3fffc7b23","reference":null,"user_id":null,"location_id":null,"source_identifier":null,"source_url":null,"processed_at":"2021-01-05T21:35:02-05:00","device_id":null,"phone":null,"customer_locale":"en","app_id":580111,"browser_ip":"172.58.238.224","client_details":{"accept_language":"en-US,en;q=0.9","browser_height":657,"browser_ip":"172.58.238.224","browser_width":1349,"session_hash":null,"user_agent":"Mozilla\/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit\/537.36 (KHTML, like Gecko) Chrome\/87.0.4280.88 Safari\/537.36"},"landing_site_ref":null,"order_number":2586,"discount_applications":[{"type":"discount_code","value":"100.0","value_type":"percentage","allocation_method":"across","target_selection":"all","target_type":"line_item","code":"adina"}],"discount_codes":[{"code":"adina","amount":"18.00","type":"percentage"}],"note_attributes":[{"name":"Checkout-Method","value":"pickup"},{"name":"Pickup-Location-Id","value":"105225"},{"name":"Pickup-Location-Company","value":"Evergreen Monsey"},{"name":"Pickup-Location-Address-Line-1","value":"59 NY-59"},{"name":"Pickup-Location-City","value":"Monsey"},{"name":"Pickup-Location-Region","value":"New York"},{"name":"Pickup-Location-Postal-Code","value":"10952"},{"name":"Pickup-Location-Country","value":"United States"}],"payment_gateway_names":[],"processing_method":"free","checkout_id":18478127907005,"source_name":"web","fulfillment_status":null,"tax_lines":[],"tags":"","contact_email":"sample#sample.com","order_status_url":"https:\/\/labelitlabels.com\/26375225421\/orders\/3491883c672f110eaab82f8dd8080052\/authenticate?key=46788d0320dc9961fed8c81630484581","presentment_currency":"USD","total_line_items_price_set":{"shop_money":{"amount":"18.00","currency_code":"USD"},"presentment_money":{"amount":"18.00","currency_code":"USD"}},"total_discounts_set":{"shop_money":{"amount":"18.00","currency_code":"USD"},"presentment_money":{"amount":"18.00","currency_code":"USD"}},"total_shipping_price_set":{"shop_money":{"amount":"0.00","currency_code":"USD"},"presentment_money":{"amount":"0.00","currency_code":"USD"}},"subtotal_price_set":{"shop_money":{"amount":"0.00","currency_code":"USD"},"presentment_money":{"amount":"0.00","currency_code":"USD"}},"total_price_set":{"shop_money":{"amount":"0.00","currency_code":"USD"},"presentment_money":{"amount":"0.00","currency_code":"USD"}},"total_tax_set":{"shop_money":{"amount":"0.00","currency_code":"USD"},"presentment_money":{"amount":"0.00","currency_code":"USD"}},"line_items":[{"id":9102143324349,"variant_id":31929214402637,"title":"Bold Monogram","quantity":30,"sku":"L21","variant_title":"2\"*2\" $0.60","vendor":"Label It Labels","fulfillment_service":"manual","product_id":4374255960141,"requires_shipping":true,"taxable":true,"gift_card":false,"name":"Bold Monogram - 2\"*2\" $0.60","variant_inventory_management":null,"properties":[{"name":"Shape","value":"Square Shape"},{"name":"Choose Background","value":"#030000"},{"name":"Initial","value":"D"},{"name":"_font size Initial","value":"300.00"},{"name":"Choose Text Color","value":"White"},{"name":"Spell Name","value":"DREW FAMILY"},{"name":"_font size Spell Name","value":"33.00"},{"name":"Additional Text (optional)","value":"dairy cholov yisroel"},{"name":"_font size Additional Text (optional)","value":"12.00"},{"name":"_6","value":"PROOF"},{"name":"_Preview","value":"https:\/\/cdn.shopify.com\/s\/files\/1\/0263\/7522\/5421\/uploads\/23b9fb4ba8eb01b7ff717d39d9672c2d.png?format=png\u0026png"},{"name":"_pdf","value":"https:\/\/cdn.shopify.com\/s\/files\/1\/0263\/7522\/5421\/uploads\/5c0c23d462aa998831b0f79aabd0b9eb.pdf"},{"name":"_pplr_preview","value":"_Preview"},{"name":"_ZapietId","value":"a3c9cb049e2f631a8393cf37547623e2"}],"product_exists":true,"fulfillable_quantity":30,"grams":0,"price":"0.60","total_discount":"0.00","fulfillment_status":null,"price_set":{"shop_money":{"amount":"0.60","currency_code":"USD"},"presentment_money":{"amount":"0.60","currency_code":"USD"}},"total_discount_set":{"shop_money":{"amount":"0.00","currency_code":"USD"},"presentment_money":{"amount":"0.00","currency_code":"USD"}},"discount_allocations":[{"amount":"18.00","discount_application_index":0,"amount_set":{"shop_money":{"amount":"18.00","currency_code":"USD"},"presentment_money":{"amount":"18.00","currency_code":"USD"}}}],"duties":[],"admin_graphql_api_id":"gid:\/\/shopify\/LineItem\/9102143324349","tax_lines":[{"title":"NJ State Tax","price":"0.00","rate":0.06625,"price_set":{"shop_money":{"amount":"0.00","currency_code":"USD"},"presentment_money":{"amount":"0.00","currency_code":"USD"}}}],"origin_location":{"id":1809674076237,"country_code":"US","province_code":"NJ","name":"Label It Labels.","address1":"155 Pressburg Ln","address2":"","city":"Lakewood","zip":"08701"}}],"fulfillments":[],"refunds":[],"total_tip_received":"0.0","original_total_duties_set":null,"current_total_duties_set":null,"admin_graphql_api_id":"gid:\/\/shopify\/Order\/3175309607101","shipping_lines":[{"id":2654542987453,"title":"Pick up in Lakewood only","price":"0.00","code":"Pick up in Lakewood only","source":"shopify","phone":null,"requested_fulfillment_service_id":null,"delivery_category":null,"carrier_identifier":null,"discounted_price":"0.00","price_set":{"shop_money":{"amount":"0.00","currency_code":"USD"},"presentment_money":{"amount":"0.00","currency_code":"USD"}},"discounted_price_set":{"shop_money":{"amount":"0.00","currency_code":"USD"},"presentment_money":{"amount":"0.00","currency_code":"USD"}},"discount_allocations":[],"tax_lines":[]}],"billing_address":{"first_name":"John","address1":"123 street","phone":"(234) 567-8901","city":"Any City","zip":"08701","province":"New Jersey","country":"United States","last_name":"Smith","address2":"","company":null,"latitude":40.0963651,"longitude":-74.2067389,"name":"John Smith","country_code":"US","province_code":"NJ"},"shipping_address":{"first_name":"John","address1":"123 street","phone":"(234) 567-8901","city":"Any City","zip":"08701","province":"New Jersey","country":"United States","last_name":"Smith","address2":"","company":null,"latitude":40.0963651,"longitude":-74.2067389,"name":"John Smith","country_code":"US","province_code":"NJ"},"customer":{"id":4602994983101,"email":"sample#sample.com","accepts_marketing":false,"created_at":"2021-01-05T21:31:39-05:00","updated_at":"2021-01-05T21:35:07-05:00","first_name":"John","last_name":"Smith","orders_count":1,"state":"disabled","total_spent":"0.00","last_order_id":3175309607101,"note":null,"verified_email":true,"multipass_identifier":null,"tax_exempt":false,"phone":null,"tags":"","last_order_name":"#2586","currency":"USD","accepts_marketing_updated_at":"2021-01-05T21:31:39-05:00","marketing_opt_in_level":null,"admin_graphql_api_id":"gid:\/\/shopify\/Customer\/4602994983101","default_address":{"id":5617895145661,"customer_id":4602994983101,"first_name":"John","last_name":"Smith","company":null,"address1":"123 street","address2":"","city":"Any City","province":"New Jersey","country":"United States","zip":"08701","phone":"(234) 567-8901","name":"John Smith","province_code":"NJ","country_code":"US","country_name":"United States","default":true}}}
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 recieved.
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);
}}
};
}
I thought that from your title, in your json, = might be : in the value. If it's so, how about the following sample script?
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 cannot understand about the result format you expect. So in above sample script, each values are put in an array. If above result format is not the result you expected, can you provide the sample output values? By this, I would like to modify it.
In this case, please enable V8 runtime at the script editor.
Reference:
map()
Added 1:
From your updated question, I understood that data is json in your above script and you want to append the values of item_name, quantity, color, style to the active sheet in Google Spreadsheet. For this, how about the following modification?
Modified 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:
It seems that you are using Web Apps. In this case, when the script of Web Apps is modified, please redeploy the Web Apps as new version. By this, the latest script is reflected to the Web Apps. Please be carful this.
Added 2:
From your updated question, it was found that your additional value is different from your initial question. And, I understood that you wanted to retrieve the values of Shape and _pdf in properties from the added value. So in this case, I would like to modify the script as follows.
Sample script:
In this case, data is your added values. Please be careful this.
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);
}
}
In this script, when the values of properties are not existing, setValues is not run. By this, no error occurs.
Note:
In this script, your added value is used. So when the structure of value is different, the script might not be able to be used. So please be careful this.
It seems that you are using Web Apps. In this case, when the script of Web Apps is modified, please redeploy the Web Apps as new version. By this, the latest script is reflected to the Web Apps. Please be carful this.
I have pouchdb/couchbase data with equipment that has user assigned to them.
Equipment with _id and in the equipment doc there is a checkedOutBy with the user._id as the value. Within the employee object there is user.name. When I get the equipment objects how do I also get the user.name and display with the equipment.
I have searched and read about map/reduce that uses emit and do not grasp the idea. My code that i wrote from what i learned is:
by the way I am also using Angularjs.
field = "eq::"
this.getAllEquip = function(field){
function map(doc) {
if (doc.checkedOutBy !== undefined) {
emit(doc.checkedOutBy, {empName : doc.name});
}
}
var result = database.query(map, {include_docs: true,
attachments: true,
startkey: field,
endkey: field + '\uffff'})
.catch(function (err) {
//error stuff here
});
return result
};
I don't see where the two docs would get together. What am i missing? My result is empty.
The equipment json looks like:
{checkedOutBy: "us::10015", description: "3P Microsoft Surface w/stylus & power cord", equipId: "SUR1501", purchaseDate: "", rCost: 1000, id:"eq::10001"}
Emlpoyee json:
{"firstname":"Joe","gender":"male","lastname":"Blow","status":"active","title":"office","type":"userInfo","_id":"us::10015","_rev":"2-95e9f34784094104ad24bbf2894ae786"}
Thank you for your help.
Something like this should work, if I understood the question correctly:
//Sample Array of Objects with Equipment
var arr1=[{checkedout:"abc1",desc:"item1",id:1},
{checkedout:"abc2",desc:"item2",id:2},
{checkedout:"abc3",desc:"item3",id:3},
{checkedout:"abc1",desc:"item1",id:4},
{checkedout:"abc4",desc:"item3",id:5},
{checkedout:"abc6",desc:"item3",id:6}];
//Sample array of objects with Employee - the "id" in arr2 matches with "checkout" in arr1
var arr2=[{name:"john",id:"abc1"},
{name:"jack",id:"abc2"},
{name:"alice",id:"abc3"},
{name:"james",id:"abc4"}];
var result = []; //final result array
//loop through equipment array arr1
arr1.forEach(function(obj) {
var tempObj = obj;
var checkedout_id=obj.checkedout;
//do array.find which will return the first element in the array which satisfies the given function. This is absed on the assumption that that the id is unique for employee and there wont bwe multiple employees with same id (which is the "checkedout" field in equipment. If the employee is not found, it will return undefined.
var foundname = arr2.find(function(obj) {
if (obj.id == checkedout_id)
return obj.name
})
//Create the object to be inserted into the final array by adding a new key called "name", based on the result of above find function
if (foundname != undefined) {
tempObj.name=foundname.name
}
else {
tempObj.name = "Not found";
}
result.push(tempObj);
})
This is my Pouchdb solution, thank you Vijay for leading me to this solution.
First I get all my equipment. Then I use Vijay's idea to loop through the array and add the name to the object and build new array. I found there is a need to go into the .doc. part of the object as in obj.doc.checkedOutBy and tempObj.doc.name to get the job done.
$pouchDB.getAllDocs('eq::').then(function(udata){
var result = [];
//loop through equipment array
udata.rows.forEach(function(obj) {
var tempObj = obj;
var checkedout_id=obj.doc.checkedOutBy;
if (checkedout_id != undefined) {
$pouchDB.get(checkedout_id).then(function(emp){
return emp.firstname + " " + emp.lastname
}).then(function(name){
tempObj.doc.name = name;
});
}
result.push(tempObj);
})
in my service I have:
this.get = function(documentId) {
return database.get(documentId);
};
and:
this.getAllDocs = function(field){
return database.allDocs({
include_docs: true,
attachments: true,
startkey: field,
endkey: field + '\uffff'});
};