Not able to read nested properties from doPost(e) - google-apps-script

I am trying to create a webservice using the Contentservice in Apps Script and doPost(e) function to interact with Google Apps AdminDirectory service
Here is the overview of my code. I saved this as my server and published it as a websapp
function doPost(e) {
var data = e.parameter;
var resourceType = data.resourceType;
var method = data.method;
var resource = data.resource;
var resourceParams = resource.parameters;
//other code to work with AdminDIrectory
// return ContentService.createTextOutput(myoutputdata).setMimeType(ContentService.MimeType.JSON);
}
In my client code which I wrote using Apps Script to test the webservice
function test() {
var jsonData = {
authKey : 'HwZMVe3ZCGuPOhTSmdcfOqsl12345678',
resourceType : 'user',
method : 'get',
resource : {
parameters : {
userKey : 'waqar.ahmad#mydomain.com'
}
}
}
var url = 'https://script.google.com/macros/s/xyzabc12345678_wE3CQV06APje6497dyI7Hh-mQMUFM0pYDrk/exec';
var params = {
method : 'POST',
payload : jsonData
}
var resp = UrlFetchApp.fetch(url, params).getContentText();
Logger.log(resp);
}
Now when I try to read e.parameter.resource.parameters on server side, it gives error and shows that e.parameter.resource is string type.
How I can read nested objects on server side? It seems, it is recognizing only first level parameters.

Using
function doPost(e) {
return ContentService.createTextOutput(JSON.stringify(e.parameter)).setMimeType(ContentService.MimeType.JSON);
You get the response
"{"authKey":"HwZMVe3ZCGuPOhTSmdcfOqsl12345678","resource":"{parameters={userKey=waqar.ahmad#mydomain.com}}","method":"get","resourceType":"user"}"
so it looks like it is flattening any nests into a string. In the comments of a similar problem it is noted that the documentation for UrlFetchApp permits the payload to be "It can be a String, a byte array, or a JavaScript key/value map", but I assume this doesn't extend to nested key/value maps.
As noted in the other answer the solution would be to stringify the payload e.g.
var params = {
method : 'POST',
payload : {'data':JSON.stringify(jsonData)}
};
I had problems handling the payload just as a string which is why I used a key value
On the server side script you can handle with
function doPost(e) {
var data = JSON.parse(e.parameter.data);
var userKey = data.resource.parameters.userKey;
...
}

Maybe it arrives as JSON string? If that's the case you'd have to parse it back-end, something like:
resourceObj = JSON_PARSE_METHOD(e.parameter.resource);
for example in PHP this would be
$resourceObj = json_decode(e->parameter->resource);
You could find out if it's a JSON string by printing its value (or debugging it) on the backend.
Hope this helps. Cheers

Related

How to access JSON?

I am wrote API method, after calling that method , I got my response like
[
{
"spark_version": "7.6.x-scala2.12"
}
]
Now I want to have variable in my API method which store value 7.6.x-scala2.12.
API Controller method
[HttpGet]
public IActionResult GetTest(int ActivityId)
{
string StoredJson = "exec sp_GetJobJSONTest " +
"#ActivityId = " + ActivityId ;
var result = _context.Test.FromSqlRaw(StoredJson);
return Ok(result);
}
So how this variable should call on this response to get string stored in spark_version?
Thank you
As you have the JavaScript tag, here's how you'd do it in JS:
If you are able to call your API method, then you can just assign the response to a variable. For example, if you are calling it using the fetch API, it would look something like:
let apiResponse;
fetch('myApiUrl.com').then((response) => {
if (response.status === 200) {
apiResponse = response.body;
console.log('Response:', apiResponse[0]['spark_version']);
}
});
(I defined the variable outside the then to make it globally accessible)

How to post into the MongoDb collection using postman

I am trying to insert data into the MongoDb collection using postman. How would I approach this; hardcoding the data in JSON format works, but I want to be able to insert using postman in JSON format.
This is the code that allowed me to enter directly, using the post function in postman, with no input:
public async void Insert([FromBody]string value)
{
var client = new MongoClient();
var dbs = client.GetDatabase("test");
var collection = dbs.GetCollection<BsonDocument> ("restaurants");
BsonArray dataFields = new BsonArray { new BsonDocument {
{ "ID" , ObjectId.GenerateNewId()}, { "_id", ""}, } };
var document = new BsonDocument
{
{"borough",value },
{"cuisine","Korean"},
{"name","Bellaa"},
{"restaurant_id","143155"}
};
await collection.InsertOneAsync(document);
}
You can send it as raw data. You will set the post type to application/json.
This comes From the docs.

How to parse a JSONP response and return a value using OpenLayers?

I am using OpenLayers and geoserver to build an app. very new to everything and this is my first app. Now I am trying to use the WMS getFeatureInfo to fetch feature information and show in popups when users click on a feature. To get around the cross domain issue, I am now trying to get JSONP response. the response i got is:
parseResponse({"type":"FeatureCollection","features":[{"type":"Feature","id":"Fire_Boundary_Pro.1","geometry":{"type":"MultiPolygon","coordinates":[[[[414495.86280000024,6451439.778],[414501.3269999996,6451437.0124],[414572.5887000002,6451444.5907],[414614.8359000003,6451368.1611],[414679.86149999965,6451410.5882],[414793.0769999996,6451376.6343],[414905.6501000002,6451419.4576],[414983.7874999996,6451315.405],[414978.77660000045,6451203.6776],[415021.0197999999,6451127.2464],[415051.8420000002,6450994.8769],[415029.2346000001,6450855.0812],[414899.8300999999,6450693.4524],[414882.8183000004,6450595.5852],[414776.48950000014,6450517.9117],[414747.5351999998,6450426.9246],[414688.4584999997,6450384.5476],[414605.3772,6450369.8903],[414568.95940000005,6450460.3295],[414555.8437000001,6450606.8071],[414473.11259999964,6450550.2695],[414468.34250000026,6450410.6221],[414433.15529999975,6450354.4835],[414350.7204999998,6450263.0455],[414273.40699999966,6450269.3751],[414076.47389999963,6450365.4401],[414061.89190000016,6450388.7117],[414037.87590000033,6450380.4262],[413891.39940000046,6450430.6506],[413934.48699999973,6450516.7853],[413948.07650000043,6450636.9786],[413961.37650000025,6450791.4776],[414092.2400000002,6450861.1987],[414153.67080000043,6450897.9731],[414179.43510000035,6450913.3962],[414281.23610000033,6450965.7158],[414279.7922,6451137.244],[414352.3854,6451189.3169],[414395.91280000005,6451223.991],[414350.94269999955,6451360.8451],[414495.86280000024,6451439.778]]]]},"geometry_name":"the_geom","properties":{"area":8.09003398112E-5,"Shape_Leng":4319.38797802,"Shape_Area":828429.079784}}]})
However I am not sure how to parse the JSONP response and obtain a property value. I am trying to use the OpenLayers.Format.JSON.read method (not sure if this is the right way to do it) but it returns an error that it is an undefined constructor. Here is my code:
map.events.register('click', map, function (e) {
document.getElementById('nodelist').innerHTML = "Loading... please wait...";
var params = {
REQUEST: "GetFeatureInfo",
EXCEPTIONS: "text/javascript",
BBOX: map.getExtent().toBBOX(),
SERVICE: "WMS",
//use JSONP format
INFO_FORMAT: 'text/javascript',
QUERY_LAYERS: map.layers[0].params.LAYERS,
FEATURE_COUNT: 50,
Layers: 'Bushfire_Com_Study:Fire_Boundary_Pro',
WIDTH: map.size.w,
HEIGHT: map.size.h,
format: format,
styles: map.layers[0].params.STYLES,
srs: map.layers[0].params.SRS,
// handle the wms 1.3 vs wms 1.1 madness
if(map.layers[0].params.VERSION == "1.3.0") {
params.version = "1.3.0";
params.j = parseInt(e.xy.x);
params.i = parseInt(e.xy.y);
} else {
params.version = "1.1.1";
params.x = parseInt(e.xy.x);
params.y = parseInt(e.xy.y);
}
// merge filters
if(map.layers[0].params.CQL_FILTER != null) {
params.cql_filter = map.layers[0].params.CQL_FILTER;
}
if(map.layers[0].params.FILTER != null) {
params.filter = map.layers[0].params.FILTER;
}
if(map.layers[0].params.FEATUREID) {
params.featureid = map.layers[0].params.FEATUREID;
}
OpenLayers.loadURL("http://localhost:8080/geoserver/Bushfire_Com_Study/wms", params, this, setHTML, setHTML);
OpenLayers.Event.stop(e);
});
// sets the HTML provided into the nodelist element
function setHTML(response){
var json_format = new OpenLayers.Format.JSON();
var object = json_format.read(response);
document.getElementById('nodelist').innerHTML = object.features[0].properties['area'];
};
An old question but I couldn't find an answer anywhere else. Most important sources for a solution were
http://dev.openlayers.org/docs/files/OpenLayers/Protocol/Script-js.html
and
http://docs.geoserver.org/stable/en/user/services/wms/vendor.html#wms-vendor-parameters.
My code contained things similar to the following.
// The Script protocol will insert the JSONP response in to the DOM.
var protocol = new OpenLayers.Protocol.Script({
url: someUrl,
callback: someCallbackFunction,
});
// GeoServer specific settings for the JSONP request.
protocol.callbackKey = 'format_options';
protocol.callbackPrefix = 'callback:';
// WMS parameters like in the question
var params={
REQUEST: "GetFeatureInfo",
EXCEPTIONS: "text/javascript",
INFO_FORMAT: 'text/javascript',
//etc
};
// Send the request.
protocol.read({
params: params
});
// Callback to handle the response.
function someCallbackFunction(response) {
for(var feature in response.features) {
// Do something with the returned features.
}
}

getJSON with ServiceStack?

Server Side:
[RestService("/x")]
public class XFilter
{
public long[] CountryIds { get; set; }
}
public class XService : RestServiceBase<XFilter>
{
private const int PageCount = 20;
public override object OnGet(XFilter request)
{
Debugger.Break(); // request is always default at this point !!
return a;
}
}
Client Side:
<script type="text/javascript">
var requestData= "{CountryIds:[1,2]}";
$.getJSON("/api/x", requestData, function (b) {
});
It must be so easy, but I could not get XFilter on server side with this approach.
This is not valid JSON:
var requestData= "{CountryIds:[1,2]}";
All strings must be quoted, e.g:
var requestData= '{"CountryIds":[1,2]}';
var requestData = JSON.stringify({CountryIds:[1,2]}); //same as above
This would be what you would send via $.ajax POST which you might consider doing since there is no convention to handle complex types in GET requests since it has to serialize it to the queryString.
If you wanted to send a complex type as a queryString you would need to construct the URL yourself. ServiceStack uses its JSV Format to handle complex types in GET requests (which is just JSON with CSV escaping, aka. JSON without quotes).
So your request would now be:
var requestData = "[1,2]";
$.getJSON("/api/x?CountryIds=" + requestData, function (b) {
});
Re-Cap: If you wanted to send JSON you would need to do so via an ajax POST.
var requestData= "{CountryIds:[1,2]}";
Must be
var requestData= {CountryIds:[1,2]};
!
But still there is a problem in getJSON. It does not work with arrays?
Send list/array as parameter with jQuery getJson is solution for it :)
Add this:
$.ajaxSetup({
traditional: true
});

Actionscript Wait For Asynchronous Event Within Function

I need a little help with asynchronous events in ActionScript 3. I am writing a simple class that has two functions, both of which return strings(logic and code outlined below). Due to the asynchronous nature of the AS3 HTTPService, the return value line is always reached before a result is returned from the service, yielding an empty string. Is it possible to include some type of logic or statement in this function that will make it wait for a response before returning a value? Is there a framework that handles this type of stuff?
Call service
Parse JSON result, isolate value of interest
Return Value
public function geocodeLocation(address:String):Point
{
//call Google Maps API Geocode service directly over HTTP
var httpService:HTTPService = new HTTPService;
httpService.useProxy = false;
httpService.url = //"URL WILL GO HERE";
httpService.method = HTTPRequestMessage.GET_METHOD;
var asyncToken : AsyncToken = httpService.send();
asyncToken.addResponder( new AsyncResponder( onResult, onFault));
function onResult( e : ResultEvent, token : Object = null ) : void
{
//parse JSON and get value, logic not implemented yet
var jsonValue:String=""
}
function onFault( info : Object, token : Object = null ) : void
{
Alert.show(info.toString());
}
return jsonValue; //line reached before onResult fires
}
You should define onResult and onFault in your app – wherever you call geocodeLocation – and then pass them into your function as arguments after the address. Your onResult function will receive the data, parse the Point and do something with it. Your geocodeLocation function won't return anything.
public function geocodeLocation(address:String, onResult:Function, onFault:Function):void
{
//call Google Maps API Geocode service directly over HTTP
var httpService:HTTPService = new HTTPService;
httpService.useProxy = false;
httpService.url = //"URL WILL GO HERE";
httpService.method = HTTPRequestMessage.GET_METHOD;
var asyncToken : AsyncToken = httpService.send();
asyncToken.addResponder( new AsyncResponder( onResult, onFault));
}
And then in your app somewhere:
function onResult( e : ResultEvent, token : Object = null ) : void
{
var jsonValue:String=""
//parse JSON and get value, logic not implemented yet
var point:Point = new Point();
//do something with point
}
function onFault( info : Object, token : Object = null ) : void
{
Alert.show(info.toString());
//sad face
}
var address:String = "your address here";
geocodeLocation(address, onResult, onFault);
When the web service responds, control will pass either to your onResult function, where you will parse the Point and do something useful with it, or to your onFault function.
BTW you might run into problems calling the Google Maps geocoder this way, it's probably better to use the official SDK and take advantage of their code: http://code.google.com/apis/maps/documentation/flash/services.html