Looping over array in GET request - zapier

I'm trying to build a Zap in Zapier that will
Perform at single GET request that will return a JSON object.
Loop over a key in that object that contains an array.
POST a value from each array element to another URL.
I initially tried doing this with native Zapier elements, but I'm not sure how to take an action on each array item. I read in the Zapier Code documentation:
Setting the output to an array of objects will run the subsequent
steps multiple times — once for each object in the array.
So now I'm doing the GET request in a Code element:
fetch('https://domain.com/path', { headers: { 'Authorization': 'Basic xxxxxxxxxxxxxxxxxxxxxxxxx'} })
.then(function(res) {
return res.json();
}).then(function(json) {
if (typeof json.arrayElem == 'object') {
callback(json.arrayElem);
} else {
callback([]);
}
}).catch(callback);
This code returns an error:
Bargle. We hit an error creating a run javascript. :-( Error: [object
Object],[object Object],[object Object],[object Object],[object
Object],[object Object],[object Object],[object Object],[object
Object],[object Object],[object Object],[object Object]
I think I'm close, though, because if I change callback(json.arrayElem); to callback(json); I get the same error but with a single [object Object] instead of multiple.
Anyone have any pointers? I'm not married to using the Code element, but perfectly happy to if it will do what I need it to.

You should be returning proper callback arguments - the first argument is an Error or null.
Bad:
callback(json.arrayElem);
Good:
callback(null, json.arrayElem);
Same case for callback([]) vs. callback(null, []).

Related

Why am I getting oEvent.getParameter('data') undefined on dataReceived event?

this.getView().bindElement({
path: `/Employees('${this._userId}')`,
parameters: { expand: 'aaa,bbb,ccc' },
events: {
dataReceived: (oEvent) => {
this.getView().setBusy(false)
debugger
}
}
});
I can see data in the response of the $batch request.
When I put a breakpoint in the dataReceived function handler, I can also see the data via this.getView().getModel().getProperty(this.getView().getBindingContext().getPath()).
The parameter oEvent.mParameters.data exists, but the value is undefined.
If I leave out expand, the data is set. Do all entities of an associated entityset need to have an association to its parent?
This is by design according to the API reference of dataReceived:
dataReceived
[...] This event may also be fired when an error occurred.
Param
type
description
data
string
The data received; is undefined in error cases
You must have somewhere an error message in the $batch response, or the request was somehow aborted.
The missing data parameter is currently the only documented indicator for a failed request on bindObject/bindElement.
PS: See also https://github.com/SAP/openui5/issues/2263

FiveM Lua: Fivem > Web > Fivem

Struggling with this API. It works on postman - expected steps:
1- User completes chat command /user [id].
2- Script calls the API and passes [id].
3- API search DB for users with that id.
4- API passes back the username of that user and prints it into the chat.
I imagine this code is horrific and totally wrong but I am very new to Lua and FiveM code. Here is the error code.
FIVEM ERROR
[ script:TestingPOST] 2
[ script:TestingPOST] table: 000001ADC3990530
[ script:TestingPOST] 2
[ script:TestingPOST] nil
[ script:TestingPOST] SCRIPT ERROR: #TestingPOST/webhook_s.lua:16: attempt to index a nil value (local 'data')
I would really appreciate some help! :)
I have removed the API link and auth token
RegisterCommand("user", function(source, args, rawCommand)
local query = string.sub(rawCommand, 6)
print(source)
print(args)
print(query)
PerformHttpRequest('https://MYAPP.bubbleapps.io/version-test/api/1.1/wf/userdata',
function(err, text, header)
local data = json.decode(text)
TriggerClientEvent("chat:addMessage", source, {
args {
string.format("Display name is %s", data.response.displayname )
}
})
end, 'POST',
json.encode({userid = query}), {["Authorization"] = 'TOKEN'})
end)
The error indicates that the array data is nil, meaning you don't have a correct value in text (as data = json.decode(text))
I don't know much about this particular API but as a general programming advice, you should check the values of err, text and header, there's probably information as why the code isn't working. If you could post the values here that would help
You should also integrate error handling in your code in case the API is unavailable or an error occurs (by checking that err == 200 for instance)

Extracting hash key that may or may not be an array

I'm making an API call that returns XML (JSON also available) and the response body will show errors if any. There may be only one error or multiple errors. When the XML (or JSON) is parsed into a hash, the key that holds the errors will be an array when multiple errors are present but will be just a standard key when only one error is present. This makes parsing difficult as I can't seem to come up with one line of code that would fit both cases
The call to the API returns this when one error
<?xml version=\"1.0\" encoding=\"utf-8\"?><response><version>1.0</version><code>6</code><message>Data validation failed</message><errors><error><parameter>rptFilterValue1</parameter><message>Parameter is too small</message></error></errors></response>
And this when multiple errors
<?xml version=\"1.0\" encoding=\"utf-8\"?><response><version>1.0</version><code>6</code><message>Data validation failed</message><errors><error><parameter>rptFilterValue1</parameter><message>Parameter is too small</message></error><error><parameter>rptFilterValue2</parameter><message>Missing required parameter</message></error></errors></response>
I use the following to convert the XML to a Hash
Hash.from_xml(response.body).deep_symbolize_keys
This returns the following hash.
When there is only one error, the hash looks like this
{:response=>{:version=>"1.0", :code=>"6", :message=>"Data validation failed", :errors=>{:error=>{:parameter=>"rptFilterValue1", :message=>"Parameter is too small"}}}}
When there are 2 errors, the hash looks like this
{:response=>{:version=>"1.0", :code=>"6", :message=>"Data validation failed", :errors=>{:error=>[{:parameter=>"rptFilterValue1", :message=>"Parameter is too small"}, {:parameter=>"rptFilterValue2", :message=>"Missing required parameter"}]}}}
When I first tested the API response, I had multiple errors so the way I went about getting the error message was like this
data = Hash.from_xml(response.body).deep_symbolize_keys
if data[:response].has_key?(:errors)
errors = data[:response][:errors][:error].map{|x| "#{x.values[0]} #{x.values[1]}"}
However when there is only one error, the code errors out with undefined method 'values' for parameter
The only actual workaround I found was to test the class of the error key. When Array I use one method for extracting and when Hash I use another method.
if data[:response][:errors][:error].class == Array
errors = data[:response][:errors][:error].map{|x| "#{x.values[0]} #{x.values[1]}"}
else
errors = data[:response][:errors][:error].map{|x| "#{x[1]}"}
end
But I just hate hate hate it. There has to be a way to extract xml/json data from a key that may or may not be an array. The solution may be in the conversion from xml to hash rather than when parsing the actual hash. I couldn't find anything online.
I'll appreciate any help or tip.
If you're using Rails, Array#wrap is available if you can do your .dig first:
single = {:response=>{:version=>"1.0", :code=>"6", :message=>"Data validation failed", :errors=>{:error=>{:parameter=>"rptFilterValue1", :message=>"Parameter is too small"}}}}
Array.wrap(single.dig(:response, :errors, :error))
This returns an Array of size 1:
[
{
:message => "Parameter is too small",
:parameter => "rptFilterValue1"
}
]
For multiples:
multiple = {:response=>{:version=>"1.0", :code=>"6", :message=>"Data validation failed", :errors=>{:error=>[{:parameter=>"rptFilterValue1", :message=>"Parameter is too small"}, {:parameter=>"rptFilterValue2", :message=>"Missing required parameter"}]}}}
Array.wrap(multiple.dig(:response, :errors, :error))
This returns an Array of size 2:
[
{
:message => "Parameter is too small",
:parameter => "rptFilterValue1"
},
{
:message => "Missing required parameter",
:parameter => "rptFilterValue2"
}
]
You can parse XML with Nokogiri and xpath, which returns array even if selector points out single element
errors = Nokogiri::XML(xml_response).xpath('//error')
errors.map { |e| e.children.each_with_object({}) { |x, h| h[x.name] = x.content } }
Your API response with single error gives
=> [{"parameter"=>"rptFilterValue1", "message"=>"Parameter is too small"}]
and API result with multiple errors
=> [{"parameter"=>"rptFilterValue1", "message"=>"Parameter is too small"}, {"parameter"=>"rptFilterValue2", "message"=>"Missing required parameter"}]
If there's no error elements you'll get an empty array.

Zapier - Invalid API Response

I'm integrating a CRM with Facebook lead Ads using Zapier, and I can create a lead in Facebook and create it in the CRM without any issues.
After a successful post (i.e. successfully creating the lead), I'm curious what I should be returning, I would have thought
return Ok();
would have been enough. Instead, I get an error message saying:
- Got a non-object result, expected an object from create ()
What happened (You are seeing this because you are an admin):
Executing creates.ZapLead.operation.perform with bundle
Invalid API Response:
- Got a non-object result, expected an object from create ()
What should I be returning?
Code which makes the post is:
perform: (z, bundle) => {
const promise = z.request({
url: 'https://{{bundle.authData.subdomain}}.ngrok.io/api/zapier/create/lead/' + bundle.inputData.lead_type + '/' + bundle.inputData.core_customerTypeId,
method: 'POST',
body: JSON.stringify({
fields: bundle.inputData
}),
headers: {
'content-type': 'application/json'
}
});
// return promise.then((response) => JSON.parse(response.content));
return promise.then((response) => {
if (response.status != 200) {
throw new Error(`Unexpected status code ${response.status}`);
}
});
Any ideas?
Thanks,
David here, from the Zapier Platform team.
While your answer is technically correct, I wanted to add some context about the error and why your solution works.
Zapier expects a javascript object (basically anything valid and wrapped in {}) to come out of a create function. That's why JSON.parse(response.content) works, it's returning whatever the server said. Your code throws an error if it's not a 200, but doesn't return anything if it is a 200. Since undefined is not of type Object, the error you're seeing is thrown.
While {"Success":"Success","Attempt":null,"Id":null,"RequestId":null} is totally a valid response (it's an object!), it's more useful for the end-user to return data about the new lead that was created. That way, it can be used downstream for other actions.
​Let me know if you've got any other questions!
As a side note, we're very open to how to make that error message more clear; it's one devs struggle with a lot.
I think I found it. Looks like I need to return this if successful:
{"Success":"Success","Attempt":null,"Id":null,"RequestId":null}

Request object response always empty

Here's my main.js
require('sdk/request').Request({
url:'https://google.com'
,onComplete:function(response){
console.log('response',response)
}
}).get()
which gives me
console.log: extension: response constructor {}
At first I thought it was a permissions thing, but I whitelisted google and still no response
"permissions": {
"private-browsing": true
,"cross-domain-content":["https://google.com"]
}
I'm using FF31
Turns out the object wasn't actually empty, it just appeared empty in the console. When I console.log(response.text) I get the results I expect. This is probably b/c text,json, etc are prototypes of the object and the console ignores prototypes.

Resources