Any workaround?
Parsing JSON files
Moderator: kfury77
Forum rules
Please try to follow these guidelines. This will help to receive faster and more accurate response.
Please try to follow these guidelines. This will help to receive faster and more accurate response.
- Check the Support section of the corresponding product first. Chances are you will find your answer there;
- Do not create new topics for already reported problems. Add your comments to the existing topics instead;
- Create separate topic for each problem request. Do NOT post a number of non-related problem reports in a single topic;
- Give your topic a meaningful title. Titles such as "A question," "Bug report" and "Help!" provide others no clue what your message is about;
- Include the version number of the software you are using;
- This is not an official customer support helpdesk. If you need a prompt and official response, please contact our support team directly instead. It may take a while until you receive a reply in the forum;
Parsing JSON files
How can I parse a JSON file via Plugin API?
Any workaround?
Any workaround?
Web developer and designer. Using WeBuilder since 2014.
Re: Parsing JSON files
I can see a few possibilities:
1) Use TChromium and parse it using the real javascript (similarly how Emmet plugin does it)
2) Write & use a command line tool for that (call it from the plugin)
3) Parse it like a string if it's a very simple plugin using pos(), copy() etc
1) Use TChromium and parse it using the real javascript (similarly how Emmet plugin does it)
2) Write & use a command line tool for that (call it from the plugin)
3) Parse it like a string if it's a very simple plugin using pos(), copy() etc
Blumentals Software Programmer
Re: Parsing JSON files
I do it like this in one of my (unpublished) plugins:
Where "xhr.responseText" is the JSON data.
Then it's possible to access the result "objJson" using dot notation and the custom function "getProp" to access unnamed properties like arrays, like this:
Code: Select all
// Parse JSON response
SC = CreateOleObject("MSScriptControl.ScriptControl");
SC.Language = "JScript";
SC.AddCode("Object.prototype.getProp=function(i){return this[i]}");
var objJson = SC.Eval("(" + xhr.responseText + ")");Then it's possible to access the result "objJson" using dot notation and the custom function "getProp" to access unnamed properties like arrays, like this:
Code: Select all
var resObj = objJson.getProp("results");
var len = resObj.length;
for (var i=0;i<len;i++) {
var item = resObj.getProp(i);
var cdnUri = item.latest;
}There are 10 types of people in the world: Those who understand binary and those who don't.
Re: Parsing JSON files
Hi guys, thanks for your replies
I need help:
I'm writting a JSON parse library using the WeBuilder's native plugin API with the hope that It could be implemented in another plugins. Basically I have taked the first approach: parsing the JSON file with a real Javascript engine (Chromium) in a meta-json (
) , then converting it in a TStringList object, acting as an "array" (since there's no way to create custom objects in FScript, as far as I know)
The problem: apparently, there's a delay between the Chromium object and WeBuilder, so I got stranger errors:
* Sometimes the window "Parsing json file..." freezes and I have to close it manually. Even when it's programed to close automatically when the page is completely rendered.
* I can't "switch" between .json files, since only the first stays on memory, I don't know why.
* Another random errors that I can't reproduce easily
I need help:
I'm writting a JSON parse library using the WeBuilder's native plugin API with the hope that It could be implemented in another plugins. Basically I have taked the first approach: parsing the JSON file with a real Javascript engine (Chromium) in a meta-json (
The problem: apparently, there's a delay between the Chromium object and WeBuilder, so I got stranger errors:
* Sometimes the window "Parsing json file..." freezes and I have to close it manually. Even when it's programed to close automatically when the page is completely rendered.
* I can't "switch" between .json files, since only the first stays on memory, I don't know why.
* Another random errors that I can't reproduce easily
- Attachments
-
- parse_json.zip
- Here's the work-in-progress plugin, with example .json files included
- (4.17 KiB) Downloaded 736 times
Web developer and designer. Using WeBuilder since 2014.
Re: Parsing JSON files
When using WebKit/Chromium frame, there's a few things you need to be aware of.
1) It takes time opening the WebKit/Chromium frame, even if you hide it. So yo need to be sure the frame is ready before attempting to transfer data to/from Editor.
2) WebKit/Chromium frame can only transfer STRING data. So you will have to encode your data into a string format before transferring. And then decode the result when receiving.
I personally try to avoid using WebKit/Chromium frames if possible, due to these limitations. Specially after I discovered how to use "CreateOleObject()". With this you can create objects (using JScript) and then access them from FastScript. That's what the code example I posted earlier does. (You can also use "CreateOleObject()" to make XMLHttpRequest reequests etc.)
BTW: To help you with debugging of the Webkit/Chromium frame, add this function yo your WeBuilder script (Not the index.html). That will make "console.log" calls from the Webkit/Chromium frame, display the result in the WeBuilder Message window.
1) It takes time opening the WebKit/Chromium frame, even if you hide it. So yo need to be sure the frame is ready before attempting to transfer data to/from Editor.
2) WebKit/Chromium frame can only transfer STRING data. So you will have to encode your data into a string format before transferring. And then decode the result when receiving.
I personally try to avoid using WebKit/Chromium frames if possible, due to these limitations. Specially after I discovered how to use "CreateOleObject()". With this you can create objects (using JScript) and then access them from FastScript. That's what the code example I posted earlier does. (You can also use "CreateOleObject()" to make XMLHttpRequest reequests etc.)
BTW: To help you with debugging of the Webkit/Chromium frame, add this function yo your WeBuilder script (Not the index.html). That will make "console.log" calls from the Webkit/Chromium frame, display the result in the WeBuilder Message window.
Code: Select all
function OnWebkitConsoleMessage(Sender, Browser, message, source, line, Res) {
Script.Message(_t(line) + ":" + message);
}There are 10 types of people in the world: Those who understand binary and those who don't.
Re: Parsing JSON files
Another way is to expose the JSON object to FastScript as described here. Like this:
But you can only access named objects like "foo", but not arrays like "arr" due to FastScripts has no real object support 
jsonObj.arr.0 will fail at compiling, jsonObj.arr[0] gives an empty result as ActiveX arrays is not in same format as FastScript arrays.
Edit: Combining this with the custom getProp function from my eval method seems to work very well, and allows you to access indexed values.
Here's my ParseJson function. The JSON object is extended with two custom methods (getProp and getKeys), so keys and indexed data can be accessed from FastScript.
And an example function to show how to use it:
You can also use this mehod as a alternative to using Webkit/Chromium frame, if you don't need the Webkit frame visible. As it is possible to run true JavaScript code through the "htmlfile" COM object.
Only requirement is that when you call the function from FastScript, the function MUST have a parameter. If not it will return the function code itself.
Example:
Code: Select all
// load htmlfile COM object
var htmlfile = CreateOleObject("htmlfile");
// force htmlfile to load Chakra engine
htmlfile.write("<meta http-equiv='x-ua-compatible' content='IE=9' />");
// Copy htmlfile COM object's JSON object and methods into "JSON" var
var JSON = htmlfile.parentWindow.JSON;
// Unload the now unneeded COM object
htmlfile.close();
// Test string
var jsonString = "{\"foo\":\"bar\",\"arr\":[7,66,88,9,6]}";
// Parse the JSON string
var jsonObj = JSON.parse(jsonString);
// Show value of the "foo" object
Script.Message("foo: " + _t(jsonObj.foo) );
jsonObj.arr.0 will fail at compiling, jsonObj.arr[0] gives an empty result as ActiveX arrays is not in same format as FastScript arrays.
Edit: Combining this with the custom getProp function from my eval method seems to work very well, and allows you to access indexed values.
Here's my ParseJson function. The JSON object is extended with two custom methods (getProp and getKeys), so keys and indexed data can be accessed from FastScript.
Code: Select all
/**
* JSON parser using "htmlfile" OLE object.
* The JSON result object is extended with two custom methods, making data fully
* accessible from FastScript. Custom methods:
* getProp(key/index) to access properties by index or name
* getKeys(dummy) to get list of keys
*
* @param string jsonStr The JSON string to parse
*
* @return mixed variant or empty string if failure
*/
function ParseJson(jsonStr) {
// Create htmlfile COM object
var HFO = CreateOleObject("htmlfile"), jsonObj;
// force htmlfile to load Chakra engine
HFO.write("<meta http-equiv='x-ua-compatible' content='IE=9' />");
// Add custom method to objects so data can be accessed by index and name
HFO.write("<script type='text/javascript'>Object.prototype.getProp=function(t){return this[t]},Object.prototype.getKeys=function(){return Object.keys(this)};</script>");
// Parse JSON string
try jsonObj = HFO.parentWindow.JSON.parse(jsonStr);
except jsonObj = ""; // JSON parse error
// Unload COM object
HFO.close();
return jsonObj;
}
Code: Select all
function testJsonParser() {
Script.ClearMessages;
var jsonString = "{\"foo\":\"bar\",\"foo2\":28,\"arr\":[7,88,9,6]}";
var jsonObj = jsonParse(jsonString);
if (Length(jsonObj) == 0) {
Script.Message("Parse error");
return;
}
// Test of accessing keys, using custom methods getKeys and getProp
var keys = jsonObj.getKeys(0); // Must have a dummy parameter to work.
if (keys.length) {
for (var r=0;r<keys.length;r++) {
Script.Message("Key:" + keys.getProp(r));
}
}
// Test of accessing data by key, using dot notation
var foo = jsonObj.foo;
Script.Message("foo: " + _t(foo) );
// Test of accessing data by key, using custom getProp method
var foo2 = jsonObj.getProp("foo2");
Script.Message("foo2: " + _t(foo2) );
// Test of accessing data by index, using custom getProp method
var arr = jsonObj.getProp("arr");
for (var k=0; k < arr.length ; k++) {
Script.Message("arr[" + _t(k) + "]: " + _t(arr.getProp(k)) );
}
return;
}
Only requirement is that when you call the function from FastScript, the function MUST have a parameter. If not it will return the function code itself.
Example:
Code: Select all
// Create htmlfile COM object
var HFO = CreateOleObject("htmlfile"), res;
// force htmlfile to load Chakra engine
HFO.write("<meta http-equiv='x-ua-compatible' content='IE=9' />");
// Add custom JavaScript function
HFO.write("<script type='text/javascript'>var realJS = function(x) {return \'[\'+(x*x)+\']\';}</script>");
// Call custom JavaScript function
res = HFO.parentWindow.realJS(5); // Must have a parameter
Script.Message(res);
There are 10 types of people in the world: Those who understand binary and those who don't.
Re: Parsing JSON files
Code: Select all
/**
* JSON parser using "htmlfile" OLE object.
* The JSON result object is extended with two custom methods, making data fully
* accessible from FastScript. Custom methods:
* getProp(key/index) to access properties by index or name
* getKeys(dummy) to get list of keys
*
* @param string jsonStr The JSON string to parse
*
* @return mixed variant or empty string if failure
*/
function ParseJson(jsonStr) {
// Create htmlfile COM object
var HFO = CreateOleObject("htmlfile"), jsonObj;
// force htmlfile to load Chakra engine
HFO.write("<meta http-equiv='x-ua-compatible' content='IE=9' />");
// Add custom method to objects so data can be accessed by index and name
HFO.write("<script type='text/javascript'>Object.prototype.getProp=function(t){return this[t]},Object.prototype.getKeys=function(){return Object.keys(this)};</script>");
// Parse JSON string
try jsonObj = HFO.parentWindow.JSON.parse(jsonStr);
except jsonObj = ""; // JSON parse error
// Unload COM object
HFO.close();
return jsonObj;
}Web developer and designer. Using WeBuilder since 2014.
Re: Parsing JSON files
Anderson, I think there's a bug when multiple scriptable webkits are created or subscribed to, which probably appeared when embedded Chromium was updated
There is a workaround though, don't create the scriptable webkit every time but reuse it.
Having said that, it's obvious that a better method to quickly fire a JavaScript function in Chromium is necessary, so I'll try to come up with something.
Code: Select all
if (IsNull(_jsonApiWebkitWrapper)) {
_jsonApiWebkitWrapper = new TForm(WeBuilder);
_jsonApiWebkitWrapper.Width = 180;
_jsonApiWebkitWrapper.Height = 85;
_jsonApiWebkitWrapper.Position = poScreenCenter;
_jsonApiWebKit = Script.CreateScriptableWebkit(_jsonApiWebkitWrapper, Script.GetPath + "json_api/json.htm", "");
_jsonApiWebKit.OnLoadEnd = &json_api_onload_action;
_jsonApiWebKit.Subscribe("WebkitJsonAPI", &json_api_on_webkit_data);
var PlaceholderLabel = new TLabel(_jsonApiWebkitWrapper);
PlaceholderLabel.Parent = _jsonApiWebkitWrapper;
PlaceholderLabel.Caption = "Parsing Json file...";
PlaceholderLabel.SetBounds(15, 15, 165, 25);
} else {
_jsonApiWebKit.WebKit.Load(Script.GetPath + "json_api/json.htm");
}
_jsonApiWebkitWrapper.ShowModal;
//delete _jsonApiWebKit;
//delete _jsonApiWebkitWrapper;
Having said that, it's obvious that a better method to quickly fire a JavaScript function in Chromium is necessary, so I'll try to come up with something.
Blumentals Software Programmer