Getting values from JSON using appscript - json

I'm creating two-dimentional array with google appscript using chrome devices users with the JSON response from a directory. I've been able to get values. However, when I try to get recentUsers represented as:
{
"kind": "directory#chromeosdevices",
"chromeosdevices": [
{
"kind": "directory#chromeosdevice",
"etag": "1234567890"
"deviceId": "def456",
"serialNumber": "234567",
"status": "ACTIVE",
"lastSync": "2013-03-05T17:30:04.325Z",
"supportEndDate": "2014-04-05T17:30:04.325Z",
"annotatedUser": "help desk",
"annotatedLocation": "Mountain View help desk Chromebook",
"annotatedAssetId": "1234567890",
"notes": "Loaned from support",
"orderNumber": "1234",
"willAutoRenew": true,
"osVersion": "Browser Version 18.0",
"platformVersion": "Platform Version 1415.2.0",
"firmwareVersion": "Firmware Version 1.2.3.4",
"bootMode": "validated",
"lastEnrollmentTime": "2012-04-05T17:30:04.325Z",
"orgUnitPath": "corp/engineering",
"recentUsers": [
{
"type": "USER_TYPE_MANAGED",
"email": "user#customer.com" //I'm trying to get the most recent user's email
}
],
"activeTimeRanges": [
{
"date": "2012-04-05",
"activeTime": "3600000"
}
],
}
],
"nextPageToken": "abcdefghijkl123"
}
I get an array but I can't get the value. I'm trying to get the most recent user's email. Anyone have experience with appscript? I've tried recentUsers[0].email and recentUser[0]['email']. This is the code I have to far: //I commented where I'm trying to push a value
enter code here
var chromeArgs = {
maxResults: 200,
orderBy: 'annotatedUser',
projection: "FULL"
};
var getChromes = (AdminDirectory.Chromeosdevices.list('XXXXXXXXX', chromeArgs));
var chromes = getChromes.chromeosdevices;
if (chromes && chromes.length > 0) {
Logger.log('Devices:');
//2d array
var wholeValues = [];
for (var i = 0; i < chromes.length; i++){
//create a 1D array first with pushing 0,1,2 elements with a for loop
var value = [];
for (var j = 0; j < 1; j++) {
var chrms = chromes[i];
var recentUser = chrms.recentUsers;
value.push(recentUser[0].email); // Here is where I need help
}
//pushing the value array with [0,1,2] to thw wholeValues array.
wholeValues.push(value);
} // the outer for loop runs five times , so five the 0,1,2 with be pushed in to thewholevalues array by creating wholeValues[0][0],wholeValues[0][1]...till..wholeValues[4][2]
Logger.log(wholeValues); '''

You are very close, the only thing you need to change is to replace the static recentUsers[0] with dynamic recentUsers[j] within the loop
Sample:
function getChromes(){
var chromeArgs = {
maxResults: 200,
orderBy: 'annotatedUser',
projection: "FULL"
};
var getChromes = (AdminDirectory.Chromeosdevices.list('XXXXXXXXX', chromeArgs));
var chromes = getChromes.chromeosdevices;
if (chromes && chromes.length > 0) {
Logger.log('Devices:');
var wholeValues = [];
for (var i = 0; i < chromes.length; i++){
var chrms = chromes[i];
var recentUser = chrms.recentUsers;
var value = [];
for (var j = 0; j < recentUser.length; j++) {
Logger.log(recentUser[j].email);
value.push(recentUser[j].email);
}
wholeValues.push(value);
}
Logger.log(wholeValues);
}
}
Note that you need to specify the iteration limit of the inner loop dynamically j < recentUser.length; instead of j < 1 to account for different quantity of recent users for each chrome device.

Related

How to create JSON object in Google Apps Script by iterating a range

I am trying to write a script to batch update products in a Woocommerce store via Rest API. API requires to send request as a JSON object, but I can't build the Object in the necessarily format.
Object should look like this:
'{
"update": [
{
"id": 799,
"name": "product name"
},
{
"id": 800,
"name": "product name 1"
}
]
}'
I am trying to build the Object the following way, but it doesn't work:
var APIPayloadObject = {update:[]};
//starting loop
for ( i = 0; i < lastrow; i++){
var product = [];
product.push({
id: loopRange[i][0],
name: loopRange[i][1]
})
//???????
}
Logger.log(JSON.stringify(APIPayloadObject));
At question marks I don't know how to push product array into the object
Sample 1
As mentioned in my comment, the first solution is to access the update property and invoke push() on it since you already defined update to contain an Array instance:
//starting loop
for ( i = 0; i < lastrow; i++){
APIPayloadObject.update.push({
id: loopRange[i][0],
name: loopRange[i][1]
})
}
Sample 2
You can take it one step further and directly write your objects to update Array at the i index, since you start from 0:
//starting loop
for ( i = 0; i < lastrow; i++){
APIPayloadObject.update[i] = {
id: loopRange[i][0],
name: loopRange[i][1]
};
}
This is a great use case for Array.prototype.map.
// #param {sheetValues[][]} loopRange
function getPayload(loopRange) {
return JSON.stringify({
update: loopRange.map(function (row) {
return {id: row[0], name: row[1]};
})
});
}

How to set one more level in Object of a not predefined item?

The main issue is the following:
Get JSON from the server
Put data to form
Serialize form
Create JSON with correct structure
Send it to the server
I have difficulties on the fourth step, what I've done:
methods: {
onSubmit: function() {
var dataForm = new FormData(this.$refs['form']);
var data = [];
for (var _iterator = dataForm.entries(), _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : _iterator[Symbol.iterator]();;) {
var _Object$assign;
var _Helper = {};
var _ref;
if (_isArray) {
if (_i >= _iterator.length) break;
_ref = _iterator[_i++];
} else {
_i = _iterator.next();
if (_i.done) break;
_ref = _i.value;
}
var _ref2 = _ref,
key = _ref2[0],
val = _ref2[1];
Object.assign(_Helper, (_Object$assign = {}, _Object$assign[key] = val, _Object$assign));
}
}
},
Here you go - a link to the codepen.
As you can see I could create JSON like that:
{"0":"a","1":"b","2":"c","3":"d","4":"e","5":"d"}
However, I need smth like that:
{
"0": {
"text": "a"
},
"1": {
"text": "b"
},
"2": {
"text": "c"
},
"3": {
"text": "d"
},
"4": {
"text": "e"
},
"5": {
"text": "d"
}
}
What Can I do to implement it and also keep the correct structure of my JSON?
To change the format, change in the location it assigns the property value:
Object.assign(data, (_Object$assign = {}, _Object$assign[key] = {text: val}, _Object$assign));
// -------------------------------------------------------------^^^^^^^^^^^
Instead of a string (val), assign the object in the format you want ({text: val}).
Updated CodePen.
If you can use modern (ES6) JavaScript, there's a much shorter notation for that:
var [key, val] = _ref;
Object.assign(data, {[key]: {text: val}});
CodePen here.
Or (because you are using FormData#entries() you do are using modern JS):
var formData = Array.from(new FormData(this.$refs['form']).entries());
var data = Object.assign(...formData.map(([key, val]) => ({[key]: {text: val}})));
console.log(JSON.stringify(data));
Targetting IE10 and above
To target IE10 and above you'll need polyfills. The problem is not the syntax, but the absence of functions like .entries(), that will be added by the polyfills. To use the least amount possible of polyfills, you'll have to iterate the iterator "manually" (kind of like you are already). For more info, check this answer.
You can do the whole construction much more simply:
onSubmit: function () {
const dataForm = new FormData(this.$refs['form']);
const data = {};
for (const i of dataForm.entries()) {
data[i[0]] = { text: i[1] }
}
console.log(JSON.stringify(data));
}

Delete token from SAPUI5 Multi Input Field with Data Binding

in my SAPUI5 app I am using a Multi Input Field with tokens which are bound to a JSON Model. Newly added entries are saved in the JSON Model. However, when deleting a token by pressing the "x" next to the token text, the token disappears from the multi input field. But when adding a new token the deleted one reappears.
How can I ensure that the deleted entry is also deleted from the JSON Model?
This is my current code for adding the token to the model:
multiInputField.addValidator(function(args){
MessageBox.confirm("Do you really want to add Token\"" + args.text + "\"?", {
onClose: function(oAction) {
if (oAction === MessageBox.Action.OK){
var oToken = new Token({key: args.text, text: args.text});
args.asyncCallback(oToken);
var aFields = sap.ui.getCore().getView().getModel("myModel").getProperty("/Tokens");
var oNewFields= {
Tokens: args.text
};
aFields .push(oNewFields);
sap.ui.getCore().getView().getModel("myModel").setProperty("/Tokens", aFields );
sap.ui.getCore().getView().getModel("myModel").refresh();
} else {
args.asyncCallback(null);
}
},
title: "Add Token"
});
return sap.m.MultiInput.WaitForAsyncValidation;
});
I guess we can use "tokenUpdate" event for this.
For example, given that I have this MultiInput in my view:
<MultiInput width="500px" id="multiInput" suggestionItems="{ path: 'dataModel>/data'}" showValueHelp="true" tokenUpdate="onTokenUpdate">
<core:Item key="{dataModel>key}" text="{dataModel>value}"/>
</MultiInput>
then in my controller I can handle this like :
onTokenUpdate: function(oEvent) {
var sType = oEvent.getParameter("type");
if (sType === "removed") {
var sKey = oEvent.getParameter("removedTokens")[0].getProperty("key");
var oModel = this.getView().getModel("dataModel");
var aData = this.getView().getModel("dataModel").getProperty("/data");
for (var i = 0, len = aData.length; i < len; i++) {
var idx;
console.log(sKey + "-" + aData[i].key);
if (aData[i].key === sKey) {
idx = i;
}
}
aData.splice(idx, 1);
oModel.setProperty("/data", aData);
console.log(oModel);
}
}
And this is my json:
{
"data": [
{
"key": "token1",
"value": "token1"
},
{
"key": "token2",
"value": "token2"
}
]
}

Selecting a specific node in JSON using Appcelerator Titanium

Hopefully an easy question for you.
I have an API service from Rackspace which I call, recently they changed the order of some of the responses, meaning part of my app would no longer upload images to the correct POST url.
I've put a temp fix in place by hard coding the URL's it should be posting to, but I want to be sure I future proof against any changes in their API ordering or indeed any changes to the URL itself.
So, originally I was using the JSON response and choosing the first node and its children.
var CFtenantID = getRSToken.access.serviceCatalog[0].endpoints[0].tenantId;
var CFregion = getRSToken.access.serviceCatalog[0].endpoints[0].region;
var CFpublicURL = getRSToken.access.serviceCatalog[0].endpoints[0].publicURL;
Now, that node has moved to position 18 in a long list. So, I can manually set the script to retrieve it.
var CFtenantID = getRSToken.access.serviceCatalog[17].endpoints[0].tenantId;
var CFregion = getRSToken.access.serviceCatalog[17].endpoints[0].region;
var CFpublicURL = getRSToken.access.serviceCatalog[17].endpoints[0].publicURL;
What I'd like to be able to do, is scan for the "name" instead and just return the CloudFiles info I need, rather than having to declare an actual number of the array.
Here is a snippet of the JSON response from Rackspace.
{
"name": "cloudFeeds",
"endpoints": [
{
"region": "LON",
"tenantId": "1234",
"publicURL": "https://lon.feeds.api.rackspacecloud.com/1234",
"internalURL": "https://atom.prod.lon3.us.ci.rackspace.net/1234"
}
],
"type": "rax:feeds"
},
{
"name": "cloudFiles",
"endpoints": [
{
"region": "LON",
"tenantId": "MossoCloudFS_xxxxxx",
"publicURL": "https://storage101.lon3.clouddrive.com/v1/MossoCloudFS_xxxxx",
"internalURL": "https://snet-storage101.lon3.clouddrive.com/v1/MossoCloudFS_xxxxx"
}
],
"type": "object-store"
},
{
"name": "cloudFilesCDN",
"endpoints": [
{
"region": "LON",
"tenantId": "MossoCloudFS_xxxxxx",
"publicURL": "https://cdn3.clouddrive.com/v1/MossoCloudFS_xxxxxx"
}
],
"type": "rax:object-cdn"
}
And here is my overall script in Appcelerator.
var authCloudFiles = Ti.Network.createHTTPClient({
onload: function() {
// output
Ti.API.info(this.responseText);
var getRSToken = JSON.parse(this.responseText);
var rsToken = getRSToken.access.token.id;
var rsTenantID = getRSToken.access.token.tenant.id;
var rsTenantName = getRSToken.access.token.tenant.name;
var CFtenantID = getRSToken.access.serviceCatalog[17].endpoints[0].tenantId;
var CFregion = getRSToken.access.serviceCatalog[17].endpoints[0].region;
var CFpublicURL = getRSToken.access.serviceCatalog[17].endpoints[0].publicURL;
var rsUserID = getRSToken.access.user.id;
Ti.App.Properties.setString('rsToken', rsToken);
Ti.App.Properties.setString('rsTenantID', rsTenantID);
Ti.App.Properties.setString('rsTenantName', rsTenantName);
Ti.App.Properties.setString('CFtenantID', CFtenantID);
Ti.App.Properties.setString('CFregion', CFregion);
Ti.App.Properties.setString('CFpublicURL', CFpublicURL);
Ti.App.Properties.setString('rsUserID', rsUserID);
//alert(rsToken);
Ti.API.info('rsToken: ' + rsToken);
Ti.API.info('rsTenantID: ' + rsTenantID);
Ti.API.info('rsTenantName: ' + rsTenantName);
Ti.API.info('CFtenantID: ' + CFtenantID);
Ti.API.info('CFregion: ' + CFregion);
Ti.API.info('CFpublicURL: ' + CFpublicURL);
Ti.API.info('rsUserID: ' + rsUserID);
// then we need to load the next step
rackspaceUpload();
}
});
authCloudFiles.open('POST', 'https://identity.api.rackspacecloud.com/v2.0/tokens');
Can anyone help?
Simon
I have never used Appcelerator Titanium before, but it looks like it is just JavaScript.
You could try replacing the following:
var CFtenantID = getRSToken.access.serviceCatalog[17].endpoints[0].tenantId;
var CFregion = getRSToken.access.serviceCatalog[17].endpoints[0].region;
var CFpublicURL = getRSToken.access.serviceCatalog[17].endpoints[0].publicURL;
with:
var CFtenantID = "";
var CFregion = "";
var CFpublicURL = "";
var catalog = getRSToken.access.serviceCatalog;
for (var i=0; i<catalog.length; i++) {
if (catalog[i].name == "cloudFiles") {
for (var j=0; i<catalog[i].endpoints.length; j++) {
if (catalog[i].endpoints[j].region == "LON") {
CFtenantID = catalog[i].endpoints[j].tenantId;
CFregion = catalog[i].endpoints[j].region;
CFpublicURL = catalog[i].endpoints[j].publicURL;
break;
}
}
}
}
My JavaScript is a little rusty though, you may want to add some additional error handling.

Trouble build a table from json file under a div

I need to get rather complicate JSON data from (large) JSON file into a table at a specific part of a page. Somehow when I ran my code, nothing happens.
Snap shoot of purchase.json file -
{
"table": {
"purchases": [
{
"First Name": "Joe",
"Last Name": "Jenson",
"Product": "Netbook Computer",
"Price": "356",
"Purchase Date": "04/04/2011",
"Unit Count": "1",
"Type": "Computer",
"Return Date": "05/03/2011",
"Seq. No.": "0"
},
{
"First Name": "Christy",
"Last Name": "Davis",
"Product": "iPad",
"Price": "656",
"Purchase Date": "04/07/2011",
"Unit Count": "1",
"Type": "Computer",
"Return Date": "05/06/2011",
"Seq. No.": "10"
},
{
"First Name": "Justin",
"Last Name": "Gill",
"Product": "Laptop Computer sleeve",
"Price": "699",
"Purchase Date": "04/02/2011",
"Unit Count": "1",
"Type": "Computer Assesory",
"Return Date": "05/01/2011",
"Seq. No.": "20"
}
]
}
}
The html file -
JSON to table
get json file "purchase.json"
Parse the array into a table and load it in AJAXDiv
Table header has to be pulled from the key in the key:value pair found in the JSON.
The JavaScript code I have is -
$(document).ready(function() {
//Retrieve the JSON data from the server using AJAX
$('#AJAXButton').click(function() {
$.getJSON('data/purchase.json', function(data) {
processJSON(data);
});
});
//Process and display the JSON data
function processJSON(jsondata) {
var output = '<table cellpadding="0" cellspacing="0" border="0" class="display" id="example"><thead><tr>';
// retrieve the keys and place into an array
var keys = objKeys(jsonData.table.loans[0]).join("|");
var keyData = splitString(keys);
// print header
for (var i = 0; i < keyData.length; i++)
{
output += "<th>" + keyData[i] + "</th>";
}
output += "</thead></tr><tfoot>";
// print footer
for (var i = 0; i < keyData.length; i++)
{
output += "<th>" + keyData[i] + "</th>";
}
output += "</tfoot></tr><tbody>";
// print content of the json array in tbody
for(var j=0, jj = jsonData.table.loans.length; j < jj; j++)
{
for (var k = 0, kk = keyData.length; k < kk; k++)
{
var current = keyData[k];
output +="<td>" + jsonData.table.loans[j][current] + "</td>";
}
output += "</tr>";
}
output += "</tbody></tr></table>";
//Loop through the Languages
$('#AJAXDiv').html(output);
}
// get json keys
function objKeys(obj)
{
var keys = [];
var i = 0;
for (var z in obj)
{
if (obj.hasOwnProperty(z)) {
keys[i++] = z;
}
}
return keys;
}
// split string into array
function splitString(myString)
{
var mySplitResult = myString.split("|");
return mySplitResult;
}
});
It may be that you have a variable missing, there's
function processJSON(jsondata)
But you later use
jsonData.table.loans[0] //etc....
I suggest using a debugger like Firebug or DevTools, it makes problems like this much easier to catch.
You can also use this library: Json-To-Html-Table
I use this script that i coded my self, it really builds any json table from a mysql result
o whatever the MySQL is outputting, you can rename the column names with your own labels, by the output order. Also if you give none, the default names will be generated.
It used the $post Jquery plugin-in which you can add easly with 1 line of code.
all you need is the div with table_result:
function dyna_query(label){
$.post("your_mysql_query.php",{post_limit:15},function(e){
if(e=="fail"|| e=="" ||e=="[]"){return;}
var obj=JSON.parse(e);
//get default column names based on the associative object JSON
var column_n=Object.keys(obj[0]).length/2;
var c_names=Object.keys(obj[0]).splice(column_n,column_n);
//if there are labels, then these will replace others.
if( label){c_names=label.split(",");}
var table_row="";
//initialize table
var table_format="<table border=0><tr>";
for(var r=0; r<c_names.length;r++){
table_row+="<td class=table_h>"+c_names[r]+"</td>";}
table_row+="</tr>";
for(var i=0; i<obj.length;i++){table_row+="<tr>";
for(var c=0; c<c_names.length;c++){table_row+="<td class='table_bb'>"+obj[i][c]+" </td>";}table_row+="</tr>";}
//get all the other fields and rows
table_format+=table_row+"</table>";
//buld the html for the div with the id table_result
$("#table_result").html(table_format);
});
}
now simply call dyna_query("c1, c2, c3"); //renames default column names
or
dyna_query(); for full output with default labels