I'm using JSON for a web application I'm developing. But for various reasons I need to create "objects" that are already defined on the client script based on the JSON response of a service call. For this I would like to use a regex expression in order to insert the "new" statements into the JSON response.
function Customer(cust)
{
this.Name = null;
this.ReferencedBy = null;
this.Address = null;
if (cust != null)
{
this.Name = cust.Name;
this.ReferencedBy = cust.ReferencedBy;
this.Address = cust.Address;
}
}
The JSON response is returned by an ASP.NET AJAX Service and it contains a "__type" member that could be used to determine the object type and insert the "new" statement.
Sample JSON:
{"__type":"Customer", "ReferencedBy":{"__type":"Customer", "Name":"Rita"}, "Name":"Joseph", "Address":"123 {drive}"}
The resulting string would look like this:
new Customer({"ReferencedBy":new Customer({"Name":"Rita"}), "Name":Joseph", "Address":"123 {drive}"})
I got this so far but it doesn't work right with the ReferencedBy member.
match:
({"__type":"Customer",)(.*?})
replace:
new Customer({$2})
Hmmm why don't you try to make a simplier way to do it? e.g.:
var myJSON = {"__type":"Customer", "ReferencedBy":{"__type":"Customer", "Name":"Rita"}, "Name":"Joseph", "Address":"123 {drive}"};
after check the type: myJSON.__type, and if it is customer, then:
new Customer({"ReferencedBy":new Customer({"Name":myJSON.ReferencedBy.Name}), "Name":myJSON.Name, "Address":myJSON.Address });
It is because you already have a defined data structure, it is not neccessary to use regex to match pattern & extract data.
Related
I have email body where there is a table which has "Client Time" as the heading of first left Column.
I want to extract this whole table but am getting Null with following exec.
let regex = /<tr><td><b>Client Time([\S\s]+)<table/;
Logger.log(regex.exec(tempbody));
Here is the extra code but that should be fine.
if ((table = regex.exec(tempbody)) !== null) {
row_regex = new RegExp(/<tr>(.+)<\/tr>/g);
let data, tempdata, rows, cell;
Logger.log(data);
while ((rows = row_regex.exec(table[1])) !== null) {
data = []
cell_regex = new RegExp(/<td.*?>(.+?)<\/td>/g);
while ((cell = cell_regex.exec(rows[1])) !== null) {
data.push(cell[1]);
}
if (!tempdata || (tempdata && tempdata.length === data.length)) {
sheet.appendRow(data);
}
tempdata = data;
}
inProcessLabel.removeFromThread(threads[i]);
}
What change do I need to do in regex, sorry I don't understand regular expressions much but believe that this same code worked for me in past.
Using regular expressions to parse HTML is not a good idea (for a number of reasons).
We have V8 now so you can simply add a proper HTML/XML parser library (written in pure Javascript with minimal dependencies) to your Apps Script project. Just get the library source in full or minified form and add it as its own script file.
Here are a few good options:
XPath (source: full | minified)
HTMLParser2-20KB (source: minified)
Epicor ERP 10.2.500 has been recently released with the addition of Epicor Functions. They can be called from within Method and Data Directives.
Do anybody has been able to do so with a Form Customization within Epicor?
This is possible via a REST call to your function API. In this case, I had a function that sent an email from some inputs.
private void epiButtonC1_Click(object sender, System.EventArgs args)
{
//API Key is included in the query param in this example.
var request = (HttpWebRequest)WebRequest.Create("https://{appserver}/{EpicorInstance}/api/v2/efx/{CompanyID}/{LibraryID}/{functionName}/?api-key={yourAPIKey}");
request.Method = "POST";
//All REST v2 requests also sent with authentication method (Token, Basic)
//This should be Base64 encoded
string username = "userName";
string password = "passWord";
string encoded = System.Convert.ToBase64String(System.Text.Encoding.GetEncoding("ISO-8859-1").GetBytes(username + ":" + password));
request.Headers.Add("Authorization", "Basic " + encoded);
//Add body to correspond to request signature
request.ContentType = "application/json";
using(var writer = new StreamWriter(request.GetRequestStream()))
{
var values = new Dictionary<string, string>;
{
{"toEmailAddress", "someEmail#email.com"},
{"fromEmailAddress","someOtherEmail#email.com"},
{"body","This is the body"},
{"subject","Hello from Client Code!"}
};
string json = JsonConvert.SerializeObject(values);
writer.Write(json);
}
using (var response = request.GetResponse())
using (var reader = new StreamReader(response.GetResponseStream()))
{
var result = reader.ReadToEnd();
epiTextBoxC1.Text = result.ToString();
}
}
Haven't done it myself personally, but looking into the first post release notes about it here leads me to believe there is no out of the box solution, yet in this version/initial release.
However I'm sure you could do a HTTP request from within the Epicor customization if you have the REST API enabled in your environment.
If you create your own dll that calls the EpicorFunction you can use it within the customization. Still looking for a way to call them directly.
REST endpoint is the recommended way to perform the function call as pointed out by a-moreng.
If for some reason you cannot use this, you can use a passthrough method to any server-side BO via a customization Adapter. For instance, create an updatable BAQ which you can call from a customization using the DynamicQueryAdapter.
Pick an arbitrary table and field to save the BAQ.
Create three string parameters to store the Function library name, the function name, and a delimited list of parameters.
On the GetList method, create a Base Processing Directive.
Split your delimited parameter list and convert them to the appropriate datatypes.
Use the resulting variables to call your function.
If desired, you can pass return variables into the ttResults of the BAQ
I'm trying to use a pre-request script to build out a request object based on data pulled from a CSV file. The problem is that the request seems to be set in stone prior to the pre-request script being run. That would seem to make this a mid-request script almost rather than a pre-request.
My code is as follows:
if(ipList === undefined) ipList = "1.2.3.4,2.3.4.5,123.234.345.465";
let ips = ipList.split(',');
let queryArray = [];
for( i=0; i<ips.length; i++){
queryArray.push({ "key": "ip", "value": ips[i] });
}
console.log(queryArray);
pm.request.url.query = queryArray;
console.log(pm.request);
When I hardcode a url query variable in the request to equal 4.3.2.1, the pm.response.url object like this:
pm.request.url.query[0] = {key:"ip", value:"4.3.2.1"}
Note that the url.query[0] part of the object matches the parameter in the actual get request.
When I change the value of pm.request.url.query to equal the new query array, however as you can see here, the query array is set correctly, but the parameters are not appended to the request URL.
So unless I'm doing something wrong, it appears that the request is immutable even to the pre-request scripts.
So my question is this:
Is there a way to modify the url params of a request prior to making the request?
BTW: I know that is might seem odd to have multiple params with the same key in a query, but that's the way this API works and hard coding multiple ip addresses in the query works just fine.
You could just assign a new value to pm.request.url.
Here I had some query params already in the URL, which I had to edit:
const urlSplit = request.url.split('?');
const paramsString = urlSplit[1]; // the second part actually represents the query string we need to modify
const eachParamArray = paramsString.split('&');
let params = {};
eachParamArray.forEach((param) => {
const key = param.split('=')[0];
const value = param.split('=')[1];
Object.assign(params, {[key]: value});
});
params.bla = params.bla + 'foobar';
newQueryString = Object.keys(params).map(key => key + '=' + params[key]).join('&');
pm.request.url = urlSplit[0] + '?' + newQueryString;
In the end, I just constructed a new URL, using the first part of the previous one & the query string with the edited bla parameter.
This seemed to work for me--it didn't change what the UI shows the query string is, but it changed what the actual request was (looking at the console log)
pm.request.url.addQueryParams(["a=1", "b=2"])
pm.request.url.query.remove("b")
I have some parameters called "script_loginAs" etc... named such that people on my team know the parameter is evaluated and not sent.
I am trying to use Twitter typeahead but I am facing a problem. I don't know how typeahead passes the string to the server. Is it through a GET parameter? If so, what is the name of the parameter?
Easiest through a GET parameter, you can choose whatever parameter you want.
In JS:
$('#search').typeahead({
name: 'Search',
remote: '/search.php?query=%QUERY' // you can change anything but %QUERY, it's Typeahead default for the string to pass to backend
});
In PHP (or whatever backend you have):
$query = $_GET['query'];
Hope you get the basic idea.
You might want to consider something like this, it is a very basic remote datasource example. The get parameter in this example is 'q'
// Get your data source
var dataSource = new Bloodhound({
datumTokenizer: Bloodhound.tokenizers.obj.whitespace('value'),
queryTokenizer: Bloodhound.tokenizers.whitespace,
remote: {
url: 'path/to/your/url/json/datasource/?q=%QUERYSTRING',
wildcard: '%QUERYSTRING'
}
});
// initialize your element
var $typehead = $('#form input').typeahead(null, {
source: dataSource
});
// fire a select event, what you want once a user has selected an item
$typehead.on('typeahead:select', function(obj, datum, name) {
//your code here
});
////////////////////////////////////
# in python (django) we get a query string using the request object passed through a view like this
query = request.GET.get('q') or ""
//the caveat [or ""] is just to prevent null exceptions
///////////////////////////////////
# using php
$query = ($_GET['q']) ? $_GET['q'] : "";
Im trying to execute/consume a webservice and wondering if I am using the correct data type to return the results. String seems to work, but I receive an empty string. The service should be returning a simple string value without XML. There is a working version written in JS below, I have been asked to recreate it in Apex.
JS version (Working) - executed when a button is clicked
{!REQUIRESCRIPT("/soap/ajax/24.0/connection.js")}
{!REQUIRESCRIPT("/soap/ajax/24.0/apex.js")}
var xfolder = "TestFolder"
var parentid = "22K22"
var myvar = sforce.apex.execute("myWS","invokeWs", {folderName:xfolder,ObjectID:parentid});
window.alert('LiveLink folder created: ' + myvar);
APEX version (not working)
public with sharing class myTest {
public String getWSXMLResult() {
String tmpFolderName2 = 'TestFolder';
String tmpObjectID2 = '22K22';
String myWSXMLResult = myWS.invokeWs(tmpFolderName2,tmpObjectID2);
System.debug('XIXWS|' + myWSXMLResult);
return myWSXMLResult;
}
}
One thing I just noted while typing this out. I didn't specify the argument names for invokeWs, just the values..do I need to specify those values in the call to the WS? Such as..
myWS.invokeWs(folderName=tmpFolderName2,ObjectID=tmpObjectID2); -- this errors out btw
Thanks again everyone.