parse json with ant - json

I have an ant build script that needs to pull files down from a web server. I can use the "get" task to pull these files down one by one. However, I'd like to be able to get a list of these files first and then iterate over the list with "get" to download the files. The webserver will report the list of files in json format, but I'm not sure how to parse json with ant.
Are there any ant plugins that allow for json parsing?

I used Dave's suggestion above and it worked out pretty well. Here's what I came up with:
(Note, I ripped this out of my actual build file and tried to remove anything specific and just leave the example parts, so forgive me if it's missing anything or whatever, but it should give you an idea of how this works).
<?xml version="1.0"?>
<project name="jsonExample" default="all">
<target name="all" depends="example" />
<target name="example">
<!-- This uses Rhino - an Open Source implementation of JavaScript written in Java -
to parse JSON. -->
<script language="javascript"> <![CDATA[
importClass(java.io.File);
importClass(java.io.FileReader);
importClass(java.io.BufferedReader);
importClass(java.io.FileWriter);
importClass(java.io.BufferedWriter);
var file = new File("/path/to/myJSON.js");
fr = new FileReader(file);
br = new BufferedReader(fr);
// Read the file we just retrieved from the webservice that contains JSON.
var json = br.readLine();
// Evaluate the serialized JSON
var struct = eval("(" + json + ")");
// Get the data from
var value = struct.data.VALUE;
echo = example.createTask("echo");
echo.setMessage("Value = " + value);
echo.perform();
]]>
</script>
</target>

You can use a <script> task to run JavaScript to decode your JSON.

Here is the macro I use to load json-properties.
<macrodef name="json-properties">
<attribute name="jsonFile"/>
<sequential>
<local name="_jsonFile"/>
<property name="_jsonFile" value="#{jsonFile}"/>
<script language="javascript">//<![CDATA[
var json = new Packages.java.lang.String(
Packages.java.nio.file.Files.readAllBytes(
Packages.java.nio.file.Paths.get(project.getProperty("_jsonFile"))), "UTF-8");
var properties = JSON.parse(json);
for(key in properties) {
project.setProperty(key, properties[key]);
}
//]]></script>
</sequential>
</macrodef>

Related

Read local JSON files when dynamically creating functional tests in Intern

I am creating functional tests dynamically using Intern v4 and dojo 1.7. To accomplish this I am assigning registerSuite to a variable and attaching each test to the Tests property in registerSuite:
var registerSuite = intern.getInterface('object').registerSuite;
var assert = intern.getPlugin('chai').assert;
// ...........a bunch more code .........
registerSuite.tests['test_name'] = function() {
// READ JSON FILE HERE
var JSON = 'filename.json';
// ....... a bunch more code ........
}
That part is working great. The challenge I am having is that I need to read information from a different JSON file for each test I am dynamically creating. I cannot seem to find a way to read a JSON file while the dojo javascript is running (I want to call it in the registerSuite.tests function where it says // READ JSON FILE HERE). I have tried dojo's xhr.get, node's fs, intern's this.remote.get, nothing seems to work.
I can get a static JSON file with define(['dojo/text!./generated_tests.json']) but this does not help me because there are an unknown number of JSON files with unknown filenames, so I don't have the information I would need to call them in the declare block.
Please let me know if my description is unclear. Any help would be greatly appreciated!
Since you're creating functional tests, they'll always run in Node, so you have access to the Node environment. That means you could do something like:
var registerSuite = intern.getPlugin('interface.object').registerSuite;
var assert = intern.getPlugin('chai').assert;
var tests = {};
tests['test_name'] = function () {
var JSON = require('filename.json');
// or require.nodeRequire('filename.json')
// or JSON.parse(require('fs').readFileSync('filename.json', {
// encoding: 'utf8'
// }))
}
registerSuite('my suite', tests);
Another thing to keep in mind is assigning values to registerSuite.tests won't (or shouldn't) actually do anything. You'll need to call registerSuite, passing it your suite name and tests object, to actually register tests.

Casperjs requiring local JSON file

I am trying to require local JSON files (such as config files) and pass those JSON objects to evaluate. For each config file, evaluate function will return different results depending on the given CSS selectors from config JSON.
For example:
The folder structure is like this:
rootdir
casperExample.js
config/
|_example.json
example.json
{
"title": "$('div.pointslocal-details-section h1').text();",
"date": "$('div.pointslocal-details-time p').text();"
}
casperExample.js
var casper = require('casper').create();
var require = patchRequire(require);
var json = require('./config/example.json');
casper.start('https://website/to/be/scraped');
casper.then(function(){
this.echo(json);
pageData = this.evaluate(function(json){
var results = {};
results['title'] = json.title;
results['date'] = json.date;
return results;
}, json);
this.echo(pageData);
});
casper.run(function(){
this.exit();
});
This is what I get when I try to run: casperjs casperExample.js
CasperError: Can't find module ./config/example.json
C:/Users/msarc/coding/casper/rootdir/phantomjs:/code/bootstrap.js:307 in patchedRequire
and if I use var json = require('./config/example'); (without .json) I get
SyntaxError: Expected token '}'
C:/Users/msarc/coding/casper/rootdir/phantomjs:/platform/example.js:32 in loadModule
C:/Users/msarc/coding/casper/rootdir/phantomjs:/platform/bootstrap.js:282 in _compile
C:/Users/msarc/coding/casper/rootdir/phantomjs:/platform/bootstrap.js:126 in .js
C:/Users/msarc/coding/casper/rootdir/phantomjs:/platform/bootstrap.js:278 in _load
C:/Users/msarc/coding/casper/rootdir/phantomjs:/platform/bootstrap.js:311 in require
C:/Users/msarc/coding/casper/rootdir/phantomjs:/platform/bootstrap.js:263 in require
C:/Users/msarc/coding/casper/rootdir/phantomjs:/code/bootstrap.js:302 in patchedRequire
I want to eventually make multiple config files, each with different selectors for different websites. casperjs version: 1.1.4 phantomjs version: 2.1.1
You're requireing json file as if it were a javascript module, which it is of course not, hence the error. Instead you need to read the file and process it is JSON structure:
var fs = require('fs');
var fileContents = fs.read('config/_example.json');
var json = JSON.parse(fileContents);
Then proceed working as planned.

Twilio Synch token in ColdFusion

ColdFusion being as obscure as it is, Twilio doesn't have any SDKs for it. I'm trying to give Synch a go; I'm not getting the JSON request for the access token correct. Trying to mimic what is done by their node.js example here, I thought I could just output the JSON to the page on token.cfm:
{
"identity":"#Username#",
"token":["#AccountSID#","#APPSID#","#SECRET#"]
}
This is called from index.cfm:
<script src="js/jquery.js" ></script>
<script src="https://media.twiliocdn.com/sdk/js/sync/releases/0.5.7/twilio-sync.min.js"></script>
<script>
function fetchAccessToken(handler) {
// We use jQuery to make an Ajax request to our server to retrieve our
// Access Token
$.getJSON('token.cfm', function(data) {
// The data sent back from the server should contain a long string, which
// is the token you'll need to initialize the SDK. This string is in a format
// called JWT (JSON Web Token) - more at http://jwt.io
console.log(data.token);
// Since the starter app doesn't implement authentication, the server sends
// back a randomly generated username for the current client, which is how
// they will be identified while sending messages. If your app has a login
// system, you should use the e-mail address or username that uniquely identifies
// a user instead.
console.log(data.identity);
handler(data);
});
}
$(document).ready(function()
{
fetchAccessToken(initializeSync);
function initializeSync(tokenResponse) {
var syncClient = new Twilio.Sync.Client(tokenResponse.token);
// Use syncClient here
}
});
</script>
The response I receive is
{code: 400, message: "Unable to process JSON"}
code:
400
message:
"Unable to process JSON"
Can I accomplish this? Or, alternately, can the token be built by JavaScript alone?
Your JS is a very roundabout way of writing this:
$(function() {
$.get('token.cfm').done(function (response) {
var syncClient = new Twilio.Sync.Client(response.token);
// ... use syncClient here
});
});
but this still requires that the response is actually parseable as JSON.
If your CFM page just contains this:
<cfoutput>
{
"identity":"#Username#",
"token":["#AccountSID#","#APPSID#","#SECRET#"]
}
</cfoutput>
then this almost certainly produces syntactically wrong JSON. Don't do that.
JSON is to be produced from a data structure and a serialization function, that's no different in ColdFusion than in any other language.
<cfset AccountSID = "...">
<cfset APPSID = "...">
<cfset SECRET = "...">
<cfset tokenData = {
"identity" = Username,
"token" = [AccountSID, APPSID, SECRET]
}>
<cfcontent type="application/json"><cfoutput>#SerializeJSON(tokenData)#</cfoutput>
There are other, nicer ways of creating JSON responses, most prominently CF components with functions annotated with the "json" returnformat, but doing it manually like above is enough for a one-off.

How do I extract a variable from XML using Postman?

I'm trying to extract a SessionId from the XML which is returned from a SOAP API.
I've read through the Postman documentation (several times over) but it wasn't the most helpful in achieving my goal.
What was suggested in a few blogs was to convert the XML to JSON, and then pick out the token and it's value from there, but that didn't help either.
I used the following in my Test:
var jsonObject = xml2Json(responseBody);
postman.setGlobalVariable("Session_Id", jsonObject.SessionID);
The above created the variable "Session_Id" but didn't actually assign a value to it. I'm stumped.
I'm definitely retrieving the data from the API, and it's viewable in Postman's "Body" Response.
To extract a variable from XML using Postman, first convert your XML to JSON, using the xml2Json converter method:
var responseJson = xml2Json(responseBody);
(Where "responseBody" is your xml body.)
Then use the console.log method to output your JSON data, as such:
console.log(responseJson);
Be sure to have followed this tutorial on Enabling Chrome Dev Tools in Postman
Inside your Test Runner, run the test, then right click and "Inspect" anywhere in the Runner. Select the "Console" tab once Chrome's Dev Tools launch. Expand the "Object" part.
Then drill-down (expand) until you see the Property whose data you need.
Thereafter, set the variable by appending each drill-down level to the parameter you want:
postman.setGlobalVariable("Session_Id", responseJson.UserSessionToken.SessionID);
In this case, "responseJson" is the object, "UserSessionToken" was the next level in the drill-down, and SessionId was the parameter I needed within that.
Note: This answer was the correct solution before v7.15.0 of postman. For versions later than this, the accepted answer may not work.
Since Postman v7.15.0 the accepted answer did not work for me (it used to before the update). You have to put the path segments into square brackets.
For example, in the following XML response:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<QuotesPrivateResponse>
<lease-service>
<duration-in-months>24</duration-in-months>
</lease-service>
</QuotesPrivateResponse>
to retrieve the value duration-in-months:
var response = xml2Json(responseBody);
var duration = response["QuotesPrivateResponse"]["lease-service"]["duration-in-months"];
pm.environment.set("duration", duration);
My strong suspicion is that this behaviour is caused when any of the element names contain hyphens.
Postman v7.20.1
I'd like to add my answer since above there are a couple of details that took me a while to solve:
how to cope with a multipart SOAP response
how to manage a JSON object
responseBody definition
Here's the first lines of my XML response to analyze:
------=_Part_694527_1470506002.1584708814081
Content-Type: application/xop+xml;charset=UTF-8;type="text/xml"
Content-Transfer-Encoding: 8bit
Content-ID:
<e3bd82ac-d88f-49d4-8088-e07ff1c8d407>
<?xml version="1.0" encoding="UTF-8" ?>
<env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/">
<env:Header/>
<env:Body>
<ns2:GenericResponse xmlns:ns2="http://XXXXXXXX">
<ns2:Service IdcService="XXXXXXXX">
<ns2:Document>
<ns2:Field name="XXXXXXXX:isSetDefault">1</ns2:Field>
<ns2:Field name="XXXXXXXX">CHECKIN_UNIVERSAL</ns2:Field>
After I noticed it was a multipart I've ended up with this Postman Test:
var response = pm.response.text();
var responseBody = response.substr(response.indexOf('<env:'));
pm.test("The body of the response is a valid XML", function () {
pm.expect(xml2Json(responseBody)).to.exist;
});
pm.test("UCM file upload checkin succesfull", function(){
var responseJson = xml2Json(responseBody);
var JsonFields = (responseJson['env:Envelope']['env:Body']['ns2:GenericResponse']['ns2:Service']['ns2:Document']['ns2:Field']);
JsonFields.forEach( field => {
if (field.name == 'StatusMessage'){
console.log("Field = " + field.name);
pm.expect(field.text().to.include("Successfully checked in"));
}
});
});

Update two different values with one AJAX response

I want to update two different values with one ajax-response.
<span id="nr1">Change this</span>
<span id="nr2">and change this</span>
Now I can just change one value, I do like this:
document.getElementById('nr1').innerHTML = xmlHttp.responseText;
Is it possible to do something like this:
document.getElementById('nr1').innerHTML = xmlHttp.responseText1;
document.getElementById('nr2').innerHTML = xmlHttp.responseText2;
**** UPDATE ****
The response comes from php.
I'm totally new to JSON.
There are no responseText1 and responseText2 properties of an XMLHTTPRequest(which I assume your xmlHttp is), just responseText, so you have to return something parsable in that responseText field(like JSON). So you server may send back {"firstResponse":"value1","secondResponse":"value2"} and you can fill your fields from that JSON string. Use the json2.js library from json.org
<script type="text/javascript" src="json2.js"></script>
. . .
var theResponse = JSON.parse(xmlHttp.responseText);
document.getElementById('nr1').innerHTML = theResponse.firstResponse;
document.getElementById('nr2').innerHTML = theResponse.secondResponse;
EDIT:
In order to craft this JSON response from PHP you should use the PHP JSON libraries. There are several examples in the json_encode page that can get you started. The other code I posted(and that is posted in other responses) are all browser side javascript code.
$arr = array ('firstResponse'=>'value1','secondResponse'=>'value2');
echo json_encode($arr);
Place that code into your PHP script to generate the JSON string
{"firstResponse":"value1","secondResponse":"value2"}
Then the previously posted javascript code will parse that.
If you trust and control the server, just return a dictionary in JSON for the response and use it on the client side. So:
v = eval(xmlHttp.responseText);
document.getElementById('nr1').innerHTML = v['nr1']
document.getElementById('nr2').innerHTML = v['nr2']
As already said it would make sense to return your Ajax call as a JSON Object. I recommend the more secure JSONP call (don't know if you can use any library that supports this natively).
// Your script returns this
callback123(
{
"nr1" : "This is conten for nr1",
"nr2" : "Some content for nr2"
});
// JavaScript callback looks like this
function callback123(data)
{
for(var key in data)
document.getElementById(key).innerHTML = data[key];
}
use JSON.parse
link text