I am using JSON file and validated it on Swagger 2.0 Parser and validator
it validates it but give error of circular reference, is there any free tool or website to detect the position of circular reference in a file.
I think what you are looking for is already answered here.
Simply open your browser console and type this javascript :
function isCyclic(obj) {
var keys = [];
var stack = [];
var stackSet = new Set();
var detected = false;
function detect(obj, key) {
if (typeof obj != 'object') { return; }
if (stackSet.has(obj)) { // it's cyclic! Print the object and its locations.
var oldindex = stack.indexOf(obj);
var l1 = keys.join('.') + '.' + key;
var l2 = keys.slice(0, oldindex + 1).join('.');
console.log('CIRCULAR: ' + l1 + ' = ' + l2 + ' = ' + obj);
console.log(obj);
detected = true;
return;
}
keys.push(key);
stack.push(obj);
stackSet.add(obj);
for (var k in obj) { //dive on the object's children
if (obj.hasOwnProperty(k)) { detect(obj[k], k); }
}
keys.pop();
stack.pop();
stackSet.delete(obj);
return;
}
detect(obj, 'obj');
return detected;
}
Then you call IsCyclic(/*Json String*/), the result will show where the circular reference is.
Related
I am trying to export JSON to a CSV file.
Previously I'm using this code below to export:
convertToCSV(objArray: any) {
var array = typeof objArray != "object" ? JSON.parse(objArray) : objArray;
var str = "";
for (var i = 0; i < array.length; i++) {
var line = "";
for (var index in array[i]) {
if (line != "") line += ",";
line += array[i][index];
}
str += line + "\r\n";
}
return str;
}
exportCSVFile(headers: any, items: any[], fileTitle: string) {
if (headers) {
items.unshift(headers);
}
// Convert Object to JSON
var jsonObject = JSON.stringify(items);
var csv = this.convertToCSV(jsonObject);
var exportedFilenmae = fileTitle + ".csv" || "export.csv";
var blob = new Blob([csv], { type: "text/csv;charset=utf-8;" });
if (navigator.msSaveBlob) {
// IE 10+
navigator.msSaveBlob(blob, exportedFilenmae);
} else {
var link = document.createElement("a");
if (link.download !== undefined) {
// feature detection
// Browsers that support HTML5 download attribute
var url = URL.createObjectURL(blob);
link.setAttribute("href", url);
link.setAttribute("download", exportedFilenmae);
link.style.visibility = "hidden";
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}
}
}
exportcsv() {
this.data.forEach((item) => {
this.itemsFormatted.push({
meteringpoint: item.meteringpoint.replace(/,/g, ""), // remove commas to avoid errors,
group: item.group,
instdevice: item.instdevice,
floor: item.floor,
room: item.room,
section: item.section,
});
});
var fileTitle = "Metering Point View"; // or 'my-unique-title'
this.exportCSVFile(this.headerCSV, this.itemsFormatted, fileTitle);
}
}
But there's an error with Property 'msSaveBlob' does not exist on type 'Navigator'
Here is what I found on the internet regarding the error
So I want to ask if there is any library for exporting that has a typescript definition or is there any workaround for the problem on the code above.
Most of the libraries i found will have this problem whereby Could not find a declaration file for module 'vue-json-to-csv'. 'd:/Project/Ivory-Leaf/OAMR/VueFrontEndUi/vuefrontendui/node_modules/vue-json-to-csv/dist/vue-json-to-csv.js' implicitly has an 'any' type. Try `npm i --save-dev #types/vue-json-to-csv` if it exists or add a new declaration (.d.ts) file containing `declare module 'vue-json-to-csv';
I'm new at fumbling with Swagger, so I might be asking a silly question. Is it in any way possible to prevent the site from crashing whenever it is "unable to read from api"?
My site is working most of the time, but if there for some reason is an api that is unreadable (or just unreachable) swagger just stop working. It still displays the api's it managed to reach, but all functionality is completely gone its not even able to expand a row.
To summarize:
How do I prevent swagger from crashing, when one or more API's is unreadable and returns something like this:
Unable to read api 'XXXX' from path
http://example.com/swagger/api-docs/XXXX (server
returned undefined)
Below is my initialization of Swagger:
function loadSwagger() {
window.swaggerUi = new SwaggerUi({
url: "/frameworks/swagger/v1/api.json",
dom_id: "swagger-ui-container",
supportedSubmitMethods: ['get', 'post', 'put', 'delete'],
onComplete: function (swaggerApi, swaggerUi) {
log("Loaded SwaggerUI");
if (typeof initOAuth == "function") {
initOAuth({
clientId: "your-client-id",
realm: "your-realms",
appName: "your-app-name"
});
}
$('pre code').each(function (i, e) {
hljs.highlightBlock(e);
});
},
onFailure: function (data) {
log("Unable to Load SwaggerUI");
},
docExpansion: "none",
sorter: "alpha"
});
$('#input_apiKey').change(function () {
var key = $('#input_apiKey')[0].value;
log("key: " + key);
if (key && key.trim() != "") {
log("added key " + key);
window.authorizations.add("api_key", new ApiKeyAuthorization('api_key', key, 'header'));
}
});
$('#apiVersionSelectID').change(function () {
var sel = $('#apiVersionSelectID').val();
window.swaggerUi.url = sel;
$('#input_baseUrl').val(sel);
$('#explore').click();
});
window.swaggerUi.load();
};
I was searching for a solution to this problem too but could not find one. Here is a quick hack i did to solve the problem. Hope it can be of help to someone who is having the same trouble.
In swagger-client.js Find the function error: function (response) {
I replaced the return api_fail with addApiDeclaration to make it draw the api with some limited information even when it fails. I send in a dummy api json object with the path set to "/unable to load ' + _this.url. I send in an extra parameter that can be true or false, where true indicates that this is a failed api.
Old code:
enter cerror: function (response) {
_this.api.resourceCount += 1;
return _this.api.fail('Unable to read api \'' +
_this.name + '\' from path ' + _this.url + ' (server returned ' +response.statusText + ')');
}
New code
error: function (response) {
_this.api.resourceCount += 1;
return _this.addApiDeclaration(JSON.parse('{"apis":[{"path":"/unable to load ' + _this.url + '","operations":[{"nickname":"A","method":" "}]}],"models":{}}'), true);
}
I modified the addApiDeclaration function in the same file to display a different message for a failed api by first adding a secondary parameter to it called failed and then an if statement that check if failed is true and then change the name of the api to "FAILED TO LOAD RESOURCE " + this.name. This adds the FAILED TO LOAD RESOURCE text before the failed api.
Old code
SwaggerResource.prototype.addApiDeclaration = function (response) {
if (typeof response.produces === 'string')
this.produces = response.produces;
if (typeof response.consumes === 'string')
this.consumes = response.consumes;
if ((typeof response.basePath === 'string') && response.basePath.replace(/\s/g, '').length > 0)
this.basePath = response.basePath.indexOf('http') === -1 ? this.getAbsoluteBasePath(response.basePath) : response.basePath;
this.resourcePath = response.resourcePath;
this.addModels(response.models);
if (response.apis) {
for (var i = 0 ; i < response.apis.length; i++) {
var endpoint = response.apis[i];
this.addOperations(endpoint.path, endpoint.operations, response.consumes, response.produces);
}
}
this.api[this.name] = this;
this.ready = true;
if(this.api.resourceCount === this.api.expectedResourceCount)
this.api.finish();
return this;
};
New code
SwaggerResource.prototype.addApiDeclaration = function (response, failed) {
if (typeof response.produces === 'string')
this.produces = response.produces;
if (typeof response.consumes === 'string')
this.consumes = response.consumes;
if ((typeof response.basePath === 'string') && response.basePath.replace(/\s/g, '').length > 0)
this.basePath = response.basePath.indexOf('http') === -1 ? this.getAbsoluteBasePath(response.basePath) : response.basePath;
this.resourcePath = response.resourcePath;
this.addModels(response.models);
if (response.apis) {
for (var i = 0 ; i < response.apis.length; i++) {
var endpoint = response.apis[i];
this.addOperations(endpoint.path, endpoint.operations, response.consumes, response.produces);
}
}
if (failed == true) {
this.name = "FAILED TO LOAD RESOURCE - " + this.name;
}
this.api[this.name] = this;
this.ready = true;
if(this.api.resourceCount === this.api.expectedResourceCount)
this.api.finish();
return this;
};
In EXTJS i will use a model and store for my grid. Now is the problem that sometimes the json will not match the model. There will be less information then in my model. When this happens EXTJS will not show any data in the grid. So i looked for a fix and found this:
Ext.define('App.Reader', {
extend: 'Ext.data.reader.Json',
extractData: function(root) {
var me = this,
values = [],
records = [],
Model = me.model,
i = 0,
length = root.length,
idProp = me.getIdProperty(),
node, id, record;
if (!root.length && Ext.isObject(root)) {
root = [root];
length = 1;
}
for (; i < length; i++) {
node = root[i];
values = me.extractValues(node);
id = me.getId(node);
record = new Model(values, id, node);
records.push(record);
if (me.implicitIncludes) {
me.readAssociated(record, node);
}
}
return records;
},
extractValues: function(data) {
var fields = this.getFields(),
i = 0,
length = fields.length,
output = {},
field, value;
for (; i < length; i++) {
field = fields[i];
value = this.extractorFunctions[i](data);
if(value === undefined)
{
Ext.iterate(fields, function(key, val) {
if (data[key] === undefined & i==val) {
console.log( "Model field <" + key.name + "> does not exist in data/node.");
value = "INVALID OR MISSING FIELD NAME";
var p = 0;
for(var prop in data) {
if(p==i){
if(data.hasOwnProperty(prop))console.log("Instead of <" + key.name + "> we have <" + prop + "> with value <" + data[prop]+ ">");
}
p++;
}
}
}, this);
}
output[field.name] = value;
}
return output;
}
});
var myReader = new App.Reader({
type:'json'
});
i found this online. But when i use this with EXTJS 4.1.1 there is an error in ext-all: TypeError: j is undefined.
Where should i look for the fix for this?
There's no need to do something complicated to solve this trivial problem. Read up on Ext.data.Model and Ext.data.Field, configure your Model properly and you're all set.
I am working on some CRM 2011 Online customisations and I need to get an entity using javascript.
The entity I need will be based on the ID value of another field (a Contact entity) - this Contact ID I can get fine.
The entity I want is a custom entity. There may be multiple matches based on the Contact ID so I just want to get the first one in the list (order not important)
So far I have looked into a few ways to do this...
OData - I couldn't find enough examples on this as to what query expressions I can create, also I don't know if/how to make this work for custom entities
FetchXML - I can create a nice FetchXML query using the built-in "advanced find" too and would be happy to call this from javascript if anyone can help? I found one promising answer here but I could not see how the "results" return data was being set (Service.Fetch function)
SOAP Request - First thing I tried is a similar method as I could have done in CRM 4 but this does not seem to work. Although the request executes, my result data just seems to be empty. This is all I have code for so if any one can spot a problem with the code below then that would be great.
EDIT: I have spotted some redundant query data (I had removed link opening tags but left closing tags) - since removing this I now get XML result data... however, the where clause does not seem to apply (just get list of all entities)
var xml = "<?xml version='1.0' encoding='utf-8'?>" +
"<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\">" +
GenerateAuthenticationHeader() +
"<soap:Body>" +
"<RetrieveMultiple xmlns=\"http://schemas.microsoft.com/crm/2007/WebServices\">" +
"<query xmlns:q1=\"http://schemas.microsoft.com/crm/2006/Query\" xsi:type=\"q1:QueryExpression\">" +
"<q1:EntityName>new_vehicle</q1:EntityName>" +
"<q1:ColumnSet xsi:type='q1:ColumnSet'>" +
"<q1:Attributes>" +
"<q1:Attribute>new_vehicleid</q1:Attribute>" +
"<q1:Attribute>new_primarydriver</q1:Attribute>" +
"<q1:Attribute>statuscode</q1:Attribute>" +
"<q1:Attribute>new_registration</q1:Attribute>" +
"</q1:Attributes>" +
"</q1:ColumnSet>" +
"<q1:Distinct>false</q1:Distinct>" +
"<q1:Conditions>" +
"<q1:Condition>" +
"<q1:AttributeName>new_primarydriver</q1:AttributeName>" +
"<q1:Operator>Equal</q1:Operator>" +
"<q1:Values>" +
"<q1:Value xmlns:q2='http://microsoft.com/wsdl/types/' xsi:type='q2:guid'>" +
customerID +
"</q1:Value></q1:Values></q1:Condition>" +
"</q1:Conditions>" +
"</query></RetrieveMultiple>" +
"</soap:Body></soap:Envelope>";
var xmlHttpRequest = new ActiveXObject("Msxml2.XMLHTTP");
xmlHttpRequest.Open("POST", "/mscrmservices/2007/CrmService.asmx", false);
xmlHttpRequest.setRequestHeader("SOAPAction", "http://schemas.microsoft.com/crm/2007/WebServices/RetrieveMultiple");
xmlHttpRequest.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
xmlHttpRequest.setRequestHeader("Content-Length", xml.length);
xmlHttpRequest.send(xml);
var result = xmlHttpRequest.responseXML.xml;
var doc = new ActiveXObject("MSXML2.DOMDocument");
doc.async = false;
doc.loadXML(result);
var id = doc.selectSingleNode("//new_vehicleid");
var registration = doc.selectSingleNode("//new_registration");
if(id == null)
return null;
var vehicle = new Array();
value[0] = new Object();
value[0].id = id;
value[0].name = registration;
value[0].entityType = "new_vehicle";
return vehicle;
Sorry about the big code post but hopefully somebody who has a better understanding can help
Firstly, thanks to GlennFerrieLive for his answer post. The samples I found with the Dynamics CRM 2011 SDK (well just one in particular) really helped and the JSON parser included was perfect for the job!
I am posting this answer to give a full example of how I did it with some important comments to pay attention to which may not be so obvious from the SDK examples.
Get selected ID value from lookup field
The aim of my task was to use javascript to get set a lookup field, based on the selected data of another lookup entity. The entity to set is "new_vehicle" and the entity to query on is "customer".
First job is to get the ID value of the contact lookup field...
var customerItem = Xrm.Page.getAttribute("customerid").getValue();
var customerID = customerItem[0].id;
Querying an entity using an ID
Next is the part where I used the customerID value to find the vehicle that is currently assigned to them (the entity I want to use to set a lookup field).
First problem I found was that when querying with OData, the ID value does not seem to work with curly brackets {} - so these need to be removed...
customerID = customerID.replace('{', '').replace('}', '');
Next we get the oDataPath...
var oDataPath = Xrm.Page.context.getServerUrl() + "/xrmservices/2011/organizationdata.svc";
Then we can construct the OData query...
var filter = "/new_vehicleSet?" +
"$select=new_vehicleId,new_Registration" +
"&$filter=new_PrimaryDriver/Id eq (guid'" + customerID + "')" +
"&$orderby=new_LastAllocationDate desc" +
"&$top=1";
NOTE: There are a couple of important things to note here...
When using a guid value you must explicitly say it is a guid using (guid'xxx')
When filtering by a lookup entity (e.g. new_PrimaryDriver) you must append the value to query (e.g. Id) - this results in new_PrimaryDriver/Id
Once we have the query setup we can request the data as follows...
var retrieveRecordsReq = new XMLHttpRequest();
retrieveRecordsReq.open("GET", oDataPath + filter, true);
retrieveRecordsReq.setRequestHeader("Accept", "application/json");
retrieveRecordsReq.setRequestHeader("Content-Type", "application/json; charset=utf-8");
retrieveRecordsReq.onreadystatechange = function () {
if (this.readyState == 4) {
if (this.status == 200) {
var retrievedRecords = JSON.parse(retrieveRecordsReq.responseText).d;
if(retrievedRecords.results.length > 0)
{
var vehicle = retrievedRecords.results[0];
SetLookup("new_replacedvehicle", vehicle.new_vehicleId, vehicle.new_Registration, "new_vehicle");
}
}
}
};
retrieveRecordsReq.send();
Note that this is an asynchronous call and the onreadystatechange function will be processed upon completion, in this function we do a couple of checks to see if it was a success and the we parse the resulting JSON data - the JSON.Parse function has been included at the bottom of this post (but is available from the SDK)
Setting a lookup field using the entity queried above
The other function to make note of here is SetLookup which is just a simple helper function I added to set a lookup field. This is as follows...
function SetLookup(fieldName, idValue, textValue, typeValue)
{
var value = new Array();
value[0] = new Object();
value[0].id = idValue;
value[0].name = textValue;
value[0].typename = typeValue;
Xrm.Page.getAttribute(fieldName).setValue(value);
}
JSON parse function
This is the JSON helper function that was used in the above code (JSON.parse), pasted as it was found in the SDK...
if (!this.JSON) { this.JSON = {}; } (function () { function f(n) { return n < 10 ? '0' + n : n; } if (typeof Date.prototype.toJSON !== 'function') { Date.prototype.toJSON = function (key) { return isFinite(this.valueOf()) ? this.getUTCFullYear() + '-' + f(this.getUTCMonth() + 1) + '-' + f(this.getUTCDate()) + 'T' + f(this.getUTCHours()) + ':' + f(this.getUTCMinutes()) + ':' + f(this.getUTCSeconds()) + 'Z' : null; }; String.prototype.toJSON = Number.prototype.toJSON = Boolean.prototype.toJSON = function (key) { return this.valueOf(); }; } var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g, gap, indent, meta = { '\b': '\\b', '\t': '\\t', '\n': '\\n', '\f': '\\f', '\r': '\\r', '"': '\\"', '\\': '\\\\' }, rep; function quote(string) { escapable.lastIndex = 0; return escapable.test(string) ? '"' + string.replace(escapable, function (a) { var c = meta[a]; return typeof c === 'string' ? c : '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4); }) + '"' : '"' + string + '"'; } function str(key, holder) { var i, k, v, length, mind = gap, partial, value = holder[key]; if (value && typeof value === 'object' && typeof value.toJSON === 'function') { value = value.toJSON(key); } if (typeof rep === 'function') { value = rep.call(holder, key, value); } switch (typeof value) { case 'string': return quote(value); case 'number': return isFinite(value) ? String(value) : 'null'; case 'boolean': case 'null': return String(value); case 'object': if (!value) { return 'null'; } gap += indent; partial = []; if (Object.prototype.toString.apply(value) === '[object Array]') { length = value.length; for (i = 0; i < length; i += 1) { partial[i] = str(i, value) || 'null'; } v = partial.length === 0 ? '[]' : gap ? '[\n' + gap + partial.join(',\n' + gap) + '\n' + mind + ']' : '[' + partial.join(',') + ']'; gap = mind; return v; } if (rep && typeof rep === 'object') { length = rep.length; for (i = 0; i < length; i += 1) { k = rep[i]; if (typeof k === 'string') { v = str(k, value); if (v) { partial.push(quote(k) + (gap ? ': ' : ':') + v); } } } } else { for (k in value) { if (Object.hasOwnProperty.call(value, k)) { v = str(k, value); if (v) { partial.push(quote(k) + (gap ? ': ' : ':') + v); } } } } v = partial.length === 0 ? '{}' : gap ? '{\n' + gap + partial.join(',\n' + gap) + '\n' + mind + '}' : '{' + partial.join(',') + '}'; gap = mind; return v; } } if (typeof JSON.stringify !== 'function') { JSON.stringify = function (value, replacer, space) { var i; gap = ''; indent = ''; if (typeof space === 'number') { for (i = 0; i < space; i += 1) { indent += ' '; } } else if (typeof space === 'string') { indent = space; } rep = replacer; if (replacer && typeof replacer !== 'function' && (typeof replacer !== 'object' || typeof replacer.length !== 'number')) { throw new Error('JSON.stringify'); } return str('', { '': value }); }; } if (typeof JSON.parse !== 'function') { JSON.parse = function (text, reviver) { var j; function walk(holder, key) { var k, v, value = holder[key]; if (value && typeof value === 'object') { for (k in value) { if (Object.hasOwnProperty.call(value, k)) { v = walk(value, k); if (v !== undefined) { value[k] = v; } else { delete value[k]; } } } } return reviver.call(holder, key, value); } text = String(text); cx.lastIndex = 0; if (cx.test(text)) { text = text.replace(cx, function (a) { return '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4); }); } if (/^[\],:{}\s]*$/.test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '#').replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']').replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) { j = eval('(' + text + ')'); return typeof reviver === 'function' ? walk({ '': j }, '') : j; } throw new SyntaxError('JSON.parse'); }; } } ());
let's say you're passing an object to a function
{title:"my title", data:"corresponding data"}
how can I get the function to know what the names of the items/sub-objects are (title and data) without specifying them?
You can use a for loop as follows:
for (var key:String in obj) {
var value:String = obj[key];
trace(key + ": " + value);
}
Or use the introspection API.
The Flex 3 Help page on Performing Object Introspection has a good overview of these.
You can use a for(String in Object) loop like so:
var i:String;
for(i in object)
{
var key:String = i;
var value:Object = object[i];
// do stuff with key/value
}
PS it would make more sense obviously to use key in the loop, my example is done for the sake of demonstration.
Why was this downvoted.. Because I didn't do a function?
function findKeys(obj:Object):Array
{
var ar:Array = [];
var i:String;
for(i in obj)
{
ar.push(i);
}
return ar;
}
var ob:Object = {things:"value", other:5};
trace(findKeys(ob)); // other,things