Tableau Web Data Connector error - javascript

I am creating a Tableau Web Data Connector as per the documentation HERE.
I am running the Simulator and have setup a HTML page (as per tutorial) which calls a Javascript file that runs the Tableau WDC script as below.
(function () {
var myConnector = tableau.makeConnector();
myConnector.init = function(initCallback) {
initCallback();
tableau.submit();
};
myConnector.getSchema = function (schemaCallback) {
var cols = [
{ id : "date_of_work", alias : "Date of Work", dataType: tableau.dataTypeEnum.date },
{ id : "supervisor", alias : "Supervisor", dataType: tableau.dataTypeEnum.string }
];
var tableInfo = {
id : "test",
alias : "test",
columns : cols
};
schemaCallback([tableInfo]);
};
myConnector.getData = function (table, doneCallback) {
$.getJSON("http://myDataCall.php", function(response) {
// ERROR HERE!
var resp = response.job.job_workflows; // Response
var parsedResp = JSON.parse(resp); // Parse the response
var tableData = []; // Temp array
// Iterate over the JSON object
for (var i = 0, len = resp.length; i < len; i++) {
tableData.push({
"date_of_work": parsedResp[i]['job_status'],
"supervisor": parsedResp[i]['job_workflow_1197927'],
});
}
table.appendRows(tableData);
doneCallback();
});
};
tableau.registerConnector(myConnector);
})();
When I run the script I get the error: The WDC reported an error:
Uncaught SyntaxError: Unexpected token o in JSON at position 1 stack:SyntaxError:
Unexpected token o in JSON at position 1 at JSON.parse () at Object.success
The (abbreviated) JSON that is being returned looks as follows:
{
"employee": {
"id": 23940,
},
"company": {
"id": 1059,
},
"job": {
"id": 13712707,
"job_status_logs": [{
"id": 17330391,
}],
"company": {
"id": 1059,
},
"created_by": {
"id": 23940,
},
"job_workflows": [{
"id": 1087689283,
"job_id": 13712707,
"employee_id": null,
"template_workflow_id": 1251218,
"name": "Date of work",
"action": "datepicker",
"optional": 0,
"action_values": "",
"action_value_entered": "2017-10-12",
"nested_workflow_id": 0,
}, {
"id": 1087689284,
"job_id": 13712707,
"employee_id": null,
"template_workflow_id": 1251219,
"name": "Supervisor",
"action": "list",
"optional": 0,
"action_values": "John Doe",
"action_value_entered": "John Doe",
"nested_workflow_id": 0,
}],
"job_fields": [{
"id": 50456098,
}],
"job_status_change_messages": [{
"id": 59957985}],
"job_assets":[]
}
}
I am trying to access the job.job_workflows.action_value_entered value but keep getting the error as above.
How can I fix this error?

There are a couple of issues here.
1) The JSON sent back from your server is invalid. Here is the valid version. I recommend using a site like https://jsonformatter.curiousconcept.com/ to validate your JSON.
{
"employee": {
"id": 23940
},
"company": {
"id": 1059
},
"job": {
"id": 13712707,
"job_status_logs": [{
"id": 17330391
}],
"company": {
"id": 1059
},
"created_by": {
"id": 23940
},
"job_workflows": [{
"id": 1087689283,
"job_id": 13712707,
"employee_id": null,
"template_workflow_id": 1251218,
"name": "Date of work",
"action": "datepicker",
"optional": 0,
"action_values": "",
"action_value_entered": "2017-10-12",
"nested_workflow_id": 0
}, {
"id": 1087689284,
"job_id": 13712707,
"employee_id": null,
"template_workflow_id": 1251219,
"name": "Supervisor",
"action": "list",
"optional": 0,
"action_values": "John Doe",
"action_value_entered": "John Doe",
"nested_workflow_id": 0
}],
"job_fields": [{
"id": 50456098
}],
"job_status_change_messages": [{
"id": 59957985}],
"job_assets":[]
}
}
2) jQuery's getJson method returns an object, so you don't need to parse it. You can just use the resp variable directly like so:
var resp = response.job.job_workflows; // Response
var tableData = []; // Temp array
// Iterate over the JSON object
for (var i = 0, len = resp.length; i < len; i++) {
tableData.push({
"date_of_work": resp[i]['job_status'],
"supervisor": resp[i]['job_workflow_1197927'],
});
}
table.appendRows(tableData);
doneCallback();
Fixing those two issues should unblock you. However, you'll want to think through what data you are sending back. The current values you are sending back do not exist in the JSON (i.e. resp[i]['job_workflow_1197927']).
Instead, you could do something like this: resp[1].job_id, which would give you the job_id of each job_workflow.

Related

Postman - How to count occurrences of a specific object in a JSON response

I am new to JSON and Postman. I believe I'm trying to do something very simple.
I have created a GET request which will get a JSON response like the one below.
In the example below I want to get the count of All "IsArchived" attributes in the response;
The number of those attributes will vary from response to response.
How can I do it? Thanks in advance
{
"Id": 1328,
"Name": "AAA Test",
"Owner": {
"Id": 208,
"Name": "The Boss"
},
"FieldGroups": [
{
"Id": "c81376f0-6ac3-4028-8d61-76a0f815dbf8",
"Name": "General",
"FieldDefinitions": [
{
"Id": 1,
"DisplayName": "Product Name",
"IsArchived": false
},
{
"Id": 2,
"DisplayName": "Short Description",
"IsArchived": false
},
{
"Id": 33,
"DisplayName": "Long Description",
"IsArchived": false
},
]
},
{
"Id": "5ed8746b-0fa8-4022-8216-ad3af17db91f",
"Name": "Somethingelse",
"FieldDefinitions": [
{
"Id": 123,
"DisplayName": "Attribution",
"IsArchived": false
},
{
"Id": 1584,
"DisplayName": "FC1",
"IsArchived": false
},
{
"Id": 623,
"DisplayName": "Sizes",
"IsArchived": false,
"Owner": {
"Id": 208,
"Name": "The Boss"
},
"Unit": "",
"Options": [
{
"Id": 1,
"Value": "XS"
},
{
"Id": 2,
"Value": "S"
},
{
"Id": 3,
"Value": "M"
}
]
}
]
}
],
"IsArchived": false
"Version": 1
}
It is a rather specific solution but I hope it helps. The description is added as comments:
// Convert the response body to a JSON object
var jsonData = pm.response.json()
// Create a count variable which will be increased by 1 everytime IsArchived occurs
var count = 0;
function countIsArchived() {
// Loop through the FieldGroupsArray
_.each(jsonData.FieldGroups, (fieldGroupsArray) => {
// Loop through the FieldDefinitionsArray
_.each(fieldGroupsArray.FieldDefinitions, (fieldDefinitionsArray) => {
// Check if IsArchived exists
if(fieldDefinitionsArray.IsArchived) {
// Increase count by 1
count++;
}
});
});
// IF you want it:
// Check if IsArchived exists on the top level of the JSON response and increase count
if(jsonData.IsArchived) {
count++;
}
// IF you want it:
// Create a Postman environment variable and assign the value of count to it
pm.environment.set("count", count);
}
Additional info:
The , after the following object is not needed. It invalidates the JSON:
{
"Id": 33,
"DisplayName": "Long Description",
"IsArchived": false
}, <--

Javascript map is not a function what trying to read data

I am trying to populate a chart so I'm getting the data into 2 lists in order to do this.
This is the data:
var data = [{
"id": "622",
"name": "some name",
"boats": {
"637": {
"id": "637",
"name": " Subcat 1",
"translations": null
},
"638": {
"id": "638",
"name": "Subcat 2",
"translations": null
}
},
"image": "73e043a7fae04b55855bede22da6286b"
}];
And I am running this code in order to populate the lists:
var chList = [];
var boatList = [];
var boatCount = [];
for (var i = 0; i < data.length; i++) {
var obj = data[i];
var cl = obj.name + " [" + obj.id + "]";
if (obj.boats != null) {
chList.push(cl);
}
if(obj.boats) {
var nme = obj.boats.map( function(item){
return item.name;
});
boatList = boatList.concat(nme);
boatCount.push(nme.length);
}
}
console.log(boatList);
console.log(boatCount);
My problem is that I keep getting:
TypeError: obj.boats.map is not a function
How can I fix this?
Note: The data is actually this:
{
"id": "622",
"name": "some name",
"boats": {
"637": {
"id": "637",
"name": " Subcat 1",
"translations": null
},
"638": {
"id": "638",
"name": "Subcat 2",
"translations": null
}
},
"image": "73e043a7fae04b55855bede22da6286b"
};
But I added [ and ] to it in order to use data.length and the lists where empty too ... Do I then leave this data as it is?
The problem is that obj.boats is an object, not an array, hence doesn't have the map method.
Try this instead:
Object.keys(obj.boats).map(function(k) { return obj.boats[k].name; });
See MDN
boats is an object, not an array. Map is for arrays.
You could use a for ( in ) loop or Object.keys() to get an array of keys and work with that.
The two other answers are right, I'd change the data though:
"boats": [
{
"id": "637",
"name": " Subcat 1",
"translations": null
},
{
"id": "638",
"name": "Subcat 2",
"translations": null
}
],
Using the id as key and then giving the containing object a "id" property is kinda pointless. When you change the data to this structure your code will work fine.
Besides all other answers that already correctly point to obj.boats being an Object and not an Array, I'd like providing a solution that demonstrates the elegant beauty of Array.reduce ...
var boatChartData = [{
"id": "622",
"name": "some name",
"boats": {
"637": {
"id": "637",
"name": "Subcat 1",
"translations": null
},
"638": {
"id": "638",
"name": "Subcat 2",
"translations": null
}
},
"image": "73e043a7fae04b55855bede22da6286b"
}, {
"id": "623",
"name": "other name",
"boats": {
"639": {
"id": "639",
"name": "Supercat",
"translations": null
},
"640": {
"id": "640",
"name": "Supercat II",
"translations": null
},
"641": {
"id": "641",
"name": "Supercat III",
"translations": null
}
},
"image": "73e043a7fae04b55855bede22da6295c"
}];
function collectBoatChartData(collector, chartItem/*, idx, list*/) {
var
boatNameList,
boatMap = chartItem.boats;
if (boatMap != null) {
collector.chartItemTitleList.push([
chartItem.name,
" [",
chartItem.id,
"]"
].join(""));
boatNameList = Object.keys(boatMap).map(collector.getBoatNameByKey, boatMap);
collector.boatNameList = collector.boatNameList.concat(boatNameList);
//collector.chartItemBoatNameList.push(boatNameList);
collector.chartItemBoatCountList.push(boatNameList.length);
}
return collector;
}
var processedBoatChartData = boatChartData.reduce(collectBoatChartData, {
getBoatNameByKey: function (key) {
return this[key].name;
},
boatNameList: [],
chartItemTitleList: [],
//chartItemBoatNameList: [],
chartItemBoatCountList: []
});
console.log("processedBoatChartData.boatNameList : ", processedBoatChartData.boatNameList);
console.log("processedBoatChartData.chartItemTitleList : ", processedBoatChartData.chartItemTitleList);
//console.log("processedBoatChartData.chartItemBoatNameList : ", processedBoatChartData.chartItemBoatNameList);
console.log("processedBoatChartData.chartItemBoatCountList : ", processedBoatChartData.chartItemBoatCountList);
Note
Taking into account the OP's additional comment, mentioning the provided axample's real data structure, the above provided solution of mine just changes to ...
var boatChartData = {
"id": "622",
"name": "some name",
"boats": {
"637": {
"id": "637",
"name": "Subcat 1",
"translations": null
},
"638": {
"id": "638",
"name": "Subcat 2",
"translations": null
}
},
"image": "73e043a7fae04b55855bede22da6286b"
};
var processedBoatChartData = [boatChartData].reduce(collectBoatChartData, {
getBoatNameByKey: function (key) {
return this[key].name;
},
boatNameList: [],
chartItemTitleList: [],
//chartItemBoatNameList: [],
chartItemBoatCountList: []
});
.., proving that generic solutions can be recycled/adapted easily, if e.g. data structures do change.

Can't parse/retrieve JSON using Angular

It seems I can't parse my JSON data from Parse into my web app. When I try alert my JSON data, it shows like this
[{
"address1": "Test",
"address2": "Test",
"bathroom": "1",
"bedroom": "1",
"builtUpArea": "123",
"cityId": "1",
"countryId": "1",
"description": "Test",
"exclusive": true,
"facingDirectionId": "1",
"floorlevel": "1",
"furnishTypeId": "1",
"landArea": "123",
"landAreaTypeId": "1",
"name": "Test",
"ownerContact": "Test",
"ownerEmail": "Test",
"ownerIc": "Test",
"ownerName": "Test",
"poscode": "123",
"price": "Test",
"purchaserId": "xZyLAKnCnXt",
"remark": "Test",
"stateId": "1",
"statusId": "1",
"tenureId": "1",
"typeId": "1",
"user": {
"__type": "Pointer",
"className": "_User",
"objectId": "rquoctPnNz"
},
"objectId": "0nfSPUwgvm",
"createdAt": "2015-04-10T02:16:54.509Z",
"updatedAt": "2015-04-10T02:16:54.509Z"
}]
But nothing appear in my view page, only createdAt and updatedAt with "" symbol.
My code:
JavaScript:
var Property = Parse.Object.extend("Property");
var user = Parse.User.current();
var query = new Parse.Query(Property);
query.equalTo("user", user);
query.find({
success: function(data) {
alert(JSON.stringify(data));
$scope.properties = data;
},
error: function(object, error) {
alert(JSON.stringify(error));
}
});
HTML:
<tr ng-repeat="property in properties | filter:query">
<td>{{property.name}}</td>
<td>RM {{property.price}}</td>
<td>{{property.createdAt}}</td>
<td>{{property.updatedAt}}</td>
</tr>
I already found the answer.
$scope.properties = [];
var Property = Parse.Object.extend("Property");
var user = Parse.User.current();
var query = new Parse.Query(Property);
query.equalTo("user", user);
query.find({
success: function(data) {
var index = 0;
var Arrlen = results.length;
for (index = 0; index < Arrlen; ++index) {
var obj = results[index];
$scope.properties.push({
objectId: obj.attributes.objectId,
name: obj.attributes.name,
price: obj.attributes.price,
createdAt: obj.createdAt,
updatedAt: obj.updatedAt
});
}
},
error: function(object, error) {
alert(JSON.stringify(error));
}
});

How to display an array returned by a json object (foreach dojo)

I have a json file returned as a json object (which is an array of arrays)...below is the returned json object
{
"Info": {
"Contact": ".... ",
"title": "..."
},
"details": [
{
"ID": 1,
"Question": "User ID",
"Information": "",
}, {
"ID": 2,
"Question": "Name",
"Information": "",
}, {
"ID": 3,
"Question": "Age",
"Information": "",
}
],
"list": [
{
"No": 1,
"response": ""
}, {
"No": 2,
"response": ""
}
]
}
Now i want to display only details...the below array
"Details": [
{
"ID": 1,
"Question": "User ID",
"Information": "",
}, {
"ID": 2,
"Question": "Name",
"Information": "",
}, {
"ID": 3,
"Question": "Age",
"Information": "",
}
],
How do i do this?? please help..
Thanks in advance.
1) parse the JSON into a javascript object
var parsedJSON = JSON.parse(jsonData);
2) access the properties you want
var details = parsedJSON.details;
edit: You are parsing your javascript object back into JSON, why??
working jsfiddle
var output = "";
for(var i=0; i<json.details.length; i++) {
var detail = json.details[i];
output += detail.ID +", "+ detail.Question +", "+ detail.Information +"\n";
}
alert(output);

Getting Messages from Inbox

I have a question about the Graph API.
I use Javascript for the API and make a little test website ,where you can log in ,look for new messages and write a new status.
My problem is that I can't get the messages or the thread.
FB.api('/me/inbox',function(response) { alert(response.id); } ); don't work.
Have somebody an example for getting the messages in the inbox??
Thanks
The /me/inbox request requires that you have the read_mailbox permission granted.
Once you've got that, the /me/inbox request will return an array of Thread's, which will look something like this;
{
"data": [
{
"id": "1126884978255",
"from": {
"name": "Someone's Name",
"id": "34723472"
},
"to": {
"data": [
{
"name": "Someone's Name",
"id": "34723472"
},
{
"name": "Matt Lunn",
"id": "560914724"
}
]
},
"message": "Testing the one-ness.",
"updated_time": "2012-01-31T12:13:00+0000",
"unread": 0,
"unseen": 0,
"comments": {
"data": [
{
"id": "1126884978255_6769",
"from": {
"name": "Someone's Name",
"id": "34723472"
},
"message": "£140!?",
"created_time": "2012-01-31T11:33:15+0000"
},
{
"id": "1126884978255_6771",
"from": {
"name": "Matt Lunn",
"id": "560914724"
},
"message": "^^ month in advance as well",
"created_time": "2012-01-31T11:33:26+0000"
}
]
},
"type": "thread"
}
],
"summary": {
"unseen_count": 0,
"unread_count": 21,
"updated_time": "2012-01-31T13:19:31+0000"
}
}
So depending which ID you're after, you'll have to do;
for (var i=0;i<response.data.length;i++) {
var thread = response.data[i];
for (var j=0;j<thread.comments.data.length;j++) {
var comment = thread.comments.data[j];
console.log(comment.message);
}
}
Hopefully you get the idea...

Categories

Resources