I want to use google spreadsheet api batchUpdate to update different values with the same request.
In the documentation examples they use a dict to store the Json request but I need to set the same attribute (insertDimension) multiple times.
Here Google expected request
{
"requests": [
{
"insertDimension": {
"range": {
"sheetId": sheetId,
"dimension": "COLUMNS",
"startIndex": 2,
"endIndex": 4
},
"inheritBefore": true
}
},
{
"insertDimension": {
"range": {
"sheetId": sheetId,
"dimension": "ROWS",
"startIndex": 0,
"endIndex": 3
},
"inheritBefore": false
}
},
],
}
I tried using json.dumps
mydata = json.dumps('''
"requests": [{{"updateDimensionProperties": {"range": {"sheetId": 0,"dimension": "ROWS","startIndex": 0
"endIndex": 50
},
"properties": {
"pixelSize": 10
},
"fields": "pixelSize"
}
}
} ] ''')
but I receive this error message
"Invalid JSON payload received. Unknown name "": Root element must be a message."
Your request is invalid because it never says what kind of request it is: the insertDimension request. The correct form is
{
"requests": [
{
"insertDimension": {
# required fields at https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/request#InsertDimensionRequest
}
},
{
"insertDimension": {
# required fields at https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/request#InsertDimensionRequest
}
}]
}
By the way, one of the fields is inheritFromBefore, not inheritBefore
Related
I'm attempting to send a row to an appsheet app with their provided API. I have it all set up in app script and I'm getting a code 200 (success) but it's not adding the data to the spreadsheet. Am I doing something wrong?
function testingAPI(){
let appId = APP ID HERE
var url = `https://api.appsheet.com/api/v2/apps/${appId}/tables/opportunity/Action`;
var options = {
"method": "post",
"headers": {
"applicationAccessKey": ACCESS KEY HERE
},
"httpBody": {
"Action": "Add",
"Properties": {
"Locale": "en-US",
"Location": "47.623098, -122.330184",
"Timezone": "Pacific Standard Time",
"UserSettings": {
"Option 1": "value1",
"Option 2": "value2"
}
},
"Rows": [
{
"IntentionSetID": "1H3t8Dt",
"AgentID": "11234",
"ActivityID": 12,
"taskComplete": true,
"taskVerified": false,
"task_verified_by": "",
"proof": "https://drive.google.com/open?id=1CpzebeLtAljqHTsFHvVCCDFc-A6aXC3O",
"agent_expected_part_detail": "",
"poc_expected_part_detail": '',
"assigned_point_value": '',
"points_assigned_by": "10/31/2014",
"actual_part_detail": "8:15:25",
"verification_date": "18:30:33"
}
]
}
};
var response = UrlFetchApp.fetch(url, options);
console.log(response.getResponseCode())
}
I was able to find that the API call is indeed going through, but it's saying the "Action" is missing:
{
"RestAPIVersion": 2,
"TableName": "opportunity",
"AppTemplateVersion": "1.000247",
"Errors": "'Action' is missing.",
"AppTemplateName": "e280cf5a-e2de-4d24-89d3-95d384a2c044",
"Operation": "REST API invoke",
"RecordType": "Stop",
"Result": "Success",
"ResultSuccess": true,
"StatusCode": "OK"
}
changing httpBody to payload got me a step further, so now it's recognizing the "add" aspect, but it's still not understanding the properties correctly. it's showing a bunch of escape characters.
REST API:
{
"Action": "Add",
"Properties": {},
"Rows": []
}
Properties:
{
"RestAPIVersion": 2,
"TableName": "opportunity",
"AppTemplateVersion": "1.000250",
"Action": "Add",
"Errors": "API 'Properties' does not have unexpected Type of 'JObject'. Value is: '{\r\n \"Action\": \"Add\",\r\n \"Properties\": \"{Timezone=Pacific Standard Time, Location=47.623098, -122.330184, Locale=en-US}\",\r\n \"Rows\": \"[Ljava.lang.Object;#489763c2\"\r\n}'",
"AppTemplateName": "e280cf5a-e2de-4d24-89d3-95d384a2c044",
"Operation": "REST API invoke",
"RecordType": "Start",
"Result": "Failure"
}
The AppSheets API POST https://api.appsheet.com/api/v2/apps/{appId}/tables/{tableName}/Action can be used to invoke an action. This means that the action should be created in AppSheet before it can be called.
Resources
Invoke an Action | AppSheet
We’re requesting activity data aggregated by segments for our users via REST interface.
But for some users (not all), retrieving this data fails with a 400 Bad Request despite sharing the same request format.
An example request JSON to aggregate by segments is:
{
"aggregateBy": [
{
"dataTypeName": "com.google.activity.segment"
},
{
"dataTypeName": "com.google.calories.expended"
},
{
"dataTypeName": "com.google.step_count.delta"
}
],
"bucketByActivitySegment": {
"minDurationMillis": 60000
},
"startTimeMillis": 1627182120000,
"endTimeMillis": 1627268520000
}
For all users with recorded activity data, we receive successful responses with data points, like for example:
{
"bucket": [
{
"startTimeMillis": "1627180684015",
"endTimeMillis": "1627182139339",
"dataset": [
{
"dataSourceId": "derived:com.google.activity.summary:com.google.android.gms:aggregated",
"point": [
{
"startTimeNanos": "1627180684015000000",
"endTimeNanos": "1627182139339000000",
"dataTypeName": "com.google.activity.summary",
"originDataSourceId": "derived:com.google.activity.segment:com.google.android.gms:merge_activity_segments",
"value": [
{
"intVal": 7,
"mapVal": []
},
{
"intVal": 1455324,
"mapVal": []
},
{
"intVal": 1,
"mapVal": []
}
]
}
]
},
[...]
But for users with no recorded activity data, we always receive 400 Bad Request responses, like:
{
"error": {
"code": 400,
"message": "unknown datasource: derived:com.google.activity.segment:com.google.android.gms:merge_activity_segments",
"errors": [
{
"message": "unknown datasource: derived:com.google.activity.segment:com.google.android.gms:merge_activity_segments",
"domain": "global",
"reason": "invalidArgument"
}
],
"status": "INVALID_ARGUMENT"
}
}
We confirmed that there is no recorded activity data by aggregating activity data by time, e.g. the request
{
"aggregateBy": [
{
"dataTypeName": "com.google.activity.segment"
}
],
"bucketByTime": {
"durationMillis": 60000
},
"startTimeMillis": 1627182120000,
"endTimeMillis": 1627268520000
}
leads to a successful response with completely empty data points, like:
{
"bucket": [
{
"startTimeMillis": "1627182120000",
"endTimeMillis": "1627182180000",
"dataset": [
{
"dataSourceId": "derived:com.google.activity.summary:com.google.android.gms:aggregated",
"point": []
}
]
},
[...]
"dataset": [
{
"dataSourceId": "derived:com.google.activity.summary:com.google.android.gms:aggregated",
"point": []
}
]
}
]
}
Our questions are:
Is the 400 Bad Request response actually avoidable for users with empty data?
Or should this be considered a bug in the Google Fit API? We don't see a reason to respond with a 400 Bad Request instead of empty data when aggregating empty data by segments.
It was confirmed to us by the Google Fit team that this response behavior is not going to change, as users might already rely on it. We need to work around this, e.g. handle this error response separately, check if data is empty or something like this.
I wanna get children names of this JSON via JSONPath:
{
"status": "success",
"data": {
"blaze": {
"status": false
},
"fire": {
"status": true
},
"thunder": {
"status": false
}
}
}
and Output must be this:
["blaze", "fire", "thunder"]
but when i use data.*, i get incorrect and different response. I just want the correct parameter, because i'm using on several programming languages and i don't use the other referrences/functions.
Indeed data.* will return you the value of the objects inside the data object of your given array.
Your json -
{
"status": "success",
"data": {
"blaze": {
"status": false
},
"fire": {
"status": true
},
"thunder": {
"status": false
}
}
}
and the output of $.data.* expression -
[
{
"status": false
},
{
"status": true
},
{
"status": false
}
]
To just access the keys of data object you have to use ~ operator.
Using the expression $.data.*~ you will get the output as -
[
"blaze",
"fire",
"thunder"
]
Here you can test it. Credit to: This answer
I want to experiment with Google Datastore via Apps Script because I have a current solution based on Google sheets that runs into timeout issues inherent in constantly transacting with Drive files. I've created a test project in Google cloud with a service account and enabled library MZx5DzNPsYjVyZaR67xXJQai_d-phDA33
(cGoa) to handle the Oauth2 work. I followed the guide to start it up here and got all the pertinent confirmation that it works with my token (and that removing the token throws an 'authentication failed prompt').
Now I want to start with a basic query to display the one entity I already put in. I can use the API Explorer here and run this query body:
{
"query": {}
}
and get this result:
{
"batch": {
"entityResultType": "FULL",
"entityResults": [
{
"entity": {
"key": {
"partitionId": {
"projectId": "project-id-5200707333336492774"
},
"path": [
{
"kind": "Transaction",
"id": "5629499534213120"
}
]
},
"properties": {
"CommentIn": {
"stringValue": "My First Test Transaction"
},
"Status": {
"stringValue": "Closed"
},
"auditStatus": {
"stringValue": "Logged"
},
"User": {
"stringValue": "John Doe"
},
"Start": {
"timestampValue": "2017-08-17T18:07:04.681Z"
},
"CommentOut": {
"stringValue": "Done for today!"
},
"End": {
"timestampValue": "2017-08-17T20:07:38.058Z"
},
"Period": {
"stringValue": "08/16/2017-08/31/2017"
}
}
},
"cursor": "CkISPGogc35whh9qZWN0LWlkLTUyMDA3MDcwODA1MDY0OTI3NzRyGAsSC1RyYW5zYWN0aW9uGICAgICAgIAKDBgAIAA=",
"version": "1503004124243000"
}
],
"endCursor": "CkISPGogc35wcm9qZWN0LWlkLTUyMDAxxDcwODA1MDY0OTI3NzRyGAsSC1RyYW5zYWN0aW9uGICAgICAgIAKDBgAIAA=",
"moreResults": "NO_MORE_RESULTS"
}
}
I try to do the same thing with this code:
function doGet(e)
{
var goa = cGoa.GoaApp.createGoa('Oauth2-Service-Account',
PropertiesService.getScriptProperties()).execute(e);
if(goa.hasToken()) {var token = goa.getToken();}
var payload = {"query":{}}
;
var result = UrlFetchApp.fetch('https://datastore.googleapis.com/v1/projects/project-id-5200707333336492774:runQuery',
{
method: "POST",
headers: {authorization: "Bearer " + goa.getToken()},
muteHttpExceptions : true,
payload: payload
});
Logger.log(result.getBlob().getDataAsString());
}
and get this error in the logger:
"error": {
"code": 400,
"message": "Invalid JSON payload received. Unknown name \"query\": Cannot bind query parameter. 'query' is a message type. Parameters can only be bound to primitive types.",
"status": "INVALID_ARGUMENT",
"details": [
{
"#type": "type.googleapis.com/google.rpc.BadRequest",
"fieldViolations": [
{
"description": "Invalid JSON payload received. Unknown name \"query\": Cannot bind query parameter. 'query' is a message type. Parameters can only be bound to primitive types."
}
]
}
]
}
}
If I try to use another word such as 'resource' or 'GqlQuery', I get this error:
"error": {
"code": 400,
"message": "Invalid JSON payload received. Unknown name \"GqlQuery\": Cannot bind query parameter. Field 'GqlQuery' could not be found in request message.",
"status": "INVALID_ARGUMENT",
"details": [
{
"#type": "type.googleapis.com/google.rpc.BadRequest",
"fieldViolations": [
{
"description": "Invalid JSON payload received. Unknown name \"GqlQuery\": Cannot bind query parameter. Field 'GqlQuery' could not be found in request message."
}
]
}
]
}
}
I can't tell from the API Documentation what my syntax is supposed to be. Can anyone tell me how to compile a functional request body from Apps Script to Datastore?
You need to set the contentType of your payload as well as stringify your JSON payload as follows:
var result = UrlFetchApp.fetch(
'https://datastore.googleapis.com/v1/projects/project-id-5200707333336492774:runQuery',
{
'method':'post',
'contentType':'application/json',
'headers': {authorization: "Bearer " + goa.getToken()},
'payload':JSON.stringify(payload)
}
);
I have following JSON data coming to client. I need to extract the data somehow so I can loop through it to get all name & count values.
{
"summarydata": {
"rows": [
{
"name": "Cisco0 Webinar US",
"count": "1"
},
{
"name": "Resource Nation CC",
"count": "1"
},
{
"name": "test",
"count": "10"
},
{
"name": "test",
"count": "2"
},
{
"name": "Vendor Seek",
"count": "1"
}
]
}
}
$.extend($.jgrid.defaults,
{ datatype: 'jsonstring' },
{ ajaxGridOptions: { contentType: "application/json",
success: function (data, textStatus) {
if (textStatus == "success") {
var thegrid = $("#BuyBackGrid")[0];
thegrid.addJSONData(data.data);
var summaryresult = $.parseJSON(data.summarydata.rows[0]);
alert(summaryresult );// this gives me null
alert(data.summarydata.rows[0].name); //this gives me first name element which is "Cisco0 Webinar US" in my case.
// alert($.parseJSON(data).summarydata.rows[0].name);
}
} //end of success
}//end of ajaxGridOptions
});
Leveraging jQuery...
The $.getJSON() function parses a local JSON file and returns it as an object.
$.getJSON("myJSON.js", function(json){
alert(json.summarydata.rows[0].name);
});
You could also just do this, using the JSON library for javascript (the object is also standard in most recent browsers).
alert(JSON.parse(myJSONString).summarydata.rows[0].name);