Hello...
Trying to access or parse nested objects/arrays from JSON output but can't seem to get passed one frustrating hurdle.. I've seen a similar posting on this but doesn't quite address my issue. Any help would be appreciated. For the record, I am a newbie. Thx.
Here's the JSON output I'm trying to access. The Objects I'm looking to enumerate in the arrays are "dataPage":"data":"name": and "dataPage":"data":"backing":"switch Obj": "objectID": I am not searching on any specific object numeric value either (I am merely trying to locate unique virtual wire names to continue building further upon in my script. : (Note formatting may be offset).
{
"dataPage": {
"pagingInfo": {
"pageSize": 20,
"startIndex": 0,
"totalCount": 24,
"sortOrderAscending": true
},
"data": [
{
"objectId": "virtualwire-1",
"objectTypeName": "VirtualWire",
"name": "Transit-Network",
"backing": [
{
"switch Obj": {
"objectId": "dvs-28",
},
}
]
},
{
"objectId": "virtualwire-2",
"objectTypeName": "VirtualWire",
"name": "Web-Tier",
"backing": [
{
"switchObj": {
"objectId": "dvs-28",
},
},
]
{
"objectId": "virtualwire-3",
"objectTypeName": "VirtualWire",
"name": "App-Tier",
"backing": [
{
"switchObj": {
"objectId": "dvs-28",
},
}
]
}
]
Here's the code I'm using: Error I'm getting is "Error in (Workflow:Find One TIE Gateway / Parse JSON (item1)#56) TypeError: Cannot read property "data" from undefined
var theType = "GET";
operationUrl = "/2.0/vdn/virtualwires/"
//Set up and make request/PUT
var request = restHost.createRequest(theType, operationUrl, "");
request.setHeader("Content-Type", "application/json; charset=UTF-8");
request.setHeader("Accept", "application/json");
//Log the URL
System.log("request: " + request.fullUrl);
var response = request.execute();
//log the JSON response
System.log("vdn response: " + response.contentAsString);
var wiresObject = response.contentAsString;
var items = wiresObject.dataPage.data ("Error in (Workflow:Find One TIE Gateway / Parse JSON (item1)#56) )
//System.log("Items Output :" + items);
//Create Virtual Wire Index based on vWire Name
var theWireIndex;
for (i = 0; i < items.length; i++) {
var strName = items[i].name
//System.log(strName)
if (strName.indexOf(nameToFind + "-vWire") > -1) {
//System.log('the index with the string is: ' + i);
theWireIndex = i;
}
}
Hi there
Try this...?
//log the JSON response
System.log("vdn response: " + response.contentAsString);
// The value of 'response.contentAsString' is a 'String' type - you need to convert it to a JS 'Object' type using JSON.parse
var wiresObject = JSON.parse(response.contentAsString);
// Now you can access the content of the Object referencing the members the way you want to
var items = wiresObject.dataPage.data;
// You can also convert things back to a JSON String using this
System.log("Items Output :" + JSON.stringify(items, null, 2));
Hi there
Try this...?
//log the JSON response
System.log("vdn response: " + response.contentAsString);
// The value of 'response.contentAsString' is a 'String' type - you need to convert it to a JS 'Object' type using JSON.parse
var wiresObject = JSON.parse(response.contentAsString);
// Now you can access the content of the Object referencing the members the way you want to
var items = wiresObject.dataPage.data;
// You can also convert things back to a JSON String using this
System.log("Items Output :" + JSON.stringify(items, null, 2));
That is awesome.. It worked.. Thanks.. !! The original output appeared to look like it was still JS 'Object' type.
At the risk of appearing difficult, I've run into another snag in the last part of my script. In short, I'm trying to create a "Dynamic-type" object and return it back to vRA by "building" the Virtual Wire based on the values within the JSON.
Here's the code. I tried to apply your logic below but am getting additional "undefined" errors. For example: Error in (Workflow:Find One TIE Gateway / Parse JSON (item1)#94) TypeError: Cannot read property "backing" from undefined....Any additional help will be appreciated. Again, apologize..As a newbie, I'm plagiarizing old code..
var items = wiresObject.dataPage.data;
// You can also convert things back to a JSON String using this
System.log("Items Output :" + JSON.stringify(items, null, 2));
//Create Virtual Wire Index based on vWire Name
var theWireIndex;
for (i = 0; i < items.length; i++) {
var strName = items[i].name
//System.log(strName)
if (strName.indexOf(nameToFind + "-vWire") > -1) {
//System.log('the index with the string is: ' + i);
theWireIndex = i;
}
}
//BUILD THE WIRENAME:
var wireName;
var part1 = "vxw";
var part2 = items[theWireIndex].backing[0].switchObj.objectId; // (TypeError: Cannot read property "backing" from undefined)
var part3 = items[theWireIndex].objectId;
var part4 = "sid"
var part5 = items[theWireIndex].vdnId
var part6 = items[theWireIndex].name
System.log(part1)
System.log(part2)
System.log(part3)
System.log(part5);
System.log(part6);
wireName = part1 + "-" + part2 + "-" + part3 + "-" + part4 + "-" + part5 + "-" + part6;
return wireName;
System.log(wireName);
Try this - I re-wrote what you had a bit so it may seem a little more complicated at first
// walk the items list and find the entry with the name we want, then return the entry
function findVWireByName(vwireName, vwireList)
{
// iterate over the list and find the one with the name we need
for each(var vw in vwireList)
{
if(vw.name.indexOf(vwireName + "-vWire") > -1)
{
return vw;
}
}
return null;
}
// use the name building code to compute the wire name from the found item
function buildWireName(vwireObj)
{
System.log("Computing vWire name from object - " + JSON.stringify(vwireObj, null, 2));
var wireName;
var part1 = "vxw";
// check the backing data is present - the undefined you got previously might have indicated that
// some the data was missing for some entries?
if(vwireObj.backing != null && vwireObj.backing.length > 0)
{
var part2 = vwireObj.backing[0].switchObj.objectId; // (TypeError: Cannot read property "backing" from undefined)
}
else
{
// CHOICE TO BE MADE HERE! Pick one strategy to suit what you want
// normally, I would throw the error to kill things fast
//throw "Failed to build the vWire name - backing was not specified!!!";
// The other option is return null from this function and let the caller line deal with it...
return null;
}
var part3 = vwireObj.objectId;
var part4 = "sid"
// no field with this name on the JSON samples you gave? If you get another undefined here, this might be why
// Use System.log(JSON.stringify(vwireObj, null, 2)) to print it to the logs so it can be inspected
var part5 = vwireObj.vdnId
var part6 = vwireObj.name
System.log(part1)
System.log(part2)
System.log(part3)
System.log(part5);
System.log(part6);
wireName = part1 + "-" + part2 + "-" + part3 + "-" + part4 + "-" + part5 + "-" + part6;
System.log("Computed vWire name is " + wireName);
return wireName;
}
var items = wiresObject.dataPage.data;
//BUILD THE WIRENAME:
// Find the wire data we need first...
var myVWireItem = findVWireByName(nameToFind, items);
// cehck if we got it
if(myVWireItem != null)
{
// generate the name using the data we found
var myVWireName = buildWireName(myVWireItem);
if(myWireName != null)
{
System.log("vWire name is " + myVWireName);
}
else
{
System.log("Failed to compute vWire name - some data was missing?" + JSON.stringify(myVWireItem, null, 2));
}
}
else
{
System.log("No virtual wire found with name starting " + nameToFind);
}
I have not run this so give it a whirl and see how it goes
Hello Again;
I replied to you via PM after your last reply but you can ignore that since I believe I made a little more progress since then...Although I am grateful for the help you've provided thus far, I do run the risk of annoying you further because I need your help again. 🙄
I struggled somewhat in trying to apply your logic into my current use case over the past week or so. I think I was able to properly apply your suggestions but not entirely sure (..this is awfully new to me). Although the script is not erroring out, I'm not getting any output from the various "functions" you identified. There's a strong possibly they're not being invoked properly or at all so I'll defer to you (or anyone else) for additional help.
I've attached a file with the majority of the scripting for ease of reference.. (There's other stuff that occurs prior to this, but am having no issues there) . On that note, the JS 'Object' type input that is fed into the script at the beginning is being properly captured by the system logging and appears to be valid.
Again any additional help would be appreciated.
Thx. Ron
Hi,
Aplogies for the radio silence, I had a busy week and never got the chance to come back to you.
Fair play getting the workflow to the stage you have, glad I was able to help a little 🙂 I think the final problem you've got might be just down to where the value of 'myVwireName' is defined - the scoping rules probably mean that where you build your return object, the value is out of scope and so will be blank/undefined. I say probably there as I've seen some cases where my understanding of scope was not reflected in the code & have since learned that there are many ways to declare a variable in JS 🙂
Anyway, technical stuff aside, can I suggest a change to your latest workflow code which might help? I think there are two ways which can solve the problem here
This is the first one
// Check if we got it..
if(myVWireItem != null)
{
// SCOPE RULES CAN BE CONFUSING 🙂 - everthing inside the matching '{' and '}' braces normally only lives within that scope
// generate the name using the data we found
// the variable here *may* only live within the scope defined for this block
// Two choices - this is the first approach
var myVWireName = buildWireName(myVWireItem);
if(myVWireName != null)
{
// myVWireName variable does exist here so build the return object out now with all the values we have available
System.log("vWire name is " + myVWireName);
//Return the following Object back to vRA
var object = DynamicTypesManager.makeObject("TIE", "TIE Gateway",justName ,justName, new Array());
object.setProperty("objectId", id);
object.setProperty("GatewayName", GatewayName);
object.setProperty("ipAddress", ipAddress);
object.setProperty("NetworkName", myVWireName);
// should have all values here
resultObj = object;
}
else
{
System.log("Failed to compute vWire name - some data was missing?" + JSON.stringify(myVWireItem, null, 2));
}
}
else
{
System.log("No virtual wire found with name starting " + justName);
}
This is the second one
//Identify and Build THE WIRENAME:
// Find the wire data we need first...
var myVWireItem = findVWireByName(justName, items);
// Check if we got it..
// Define the variable OUTSIDE in the global script scope
var myVWireName;
if(myVWireItem != null)
{
// generate the name using the data we found
// now assign the
myVWireName = buildWireName(myVWireItem);
if(myVWireName != null)
{
System.log("vWire name is " + myVWireName);
}
else
{
System.log("Failed to compute vWire name - some data was missing?" + JSON.stringify(myVWireItem, null, 2));
// throw an error here to avoid building a value that cannot be used
throw "Failed to compute vWire name - cannot continue!";
}
}
else
{
throw "No virtual wire found with name starting - " + justName;
}
// NOTE:
// Throwing errors above means you can never get to here!
// Proceed to build the result
//Return the following Object back to vRA
var object = DynamicTypesManager.makeObject("TIE", "TIE Gateway",justName ,justName, new Array());
object.setProperty("objectId", id);
object.setProperty("GatewayName", GatewayName);
object.setProperty("ipAddress", ipAddress);
object.setProperty("NetworkName", myVWireName);
resultObj = object;
Can you let me know how this goes? If you have any more trouble I'm quite happy to help in any way I can
First off, want to thank you again for all your advice and work on this....Your commitment to helping the Community is admirable and much appreciated!
More developments to report on but to sum this up, everything you provided has been a success! The 2nd option above worked out fine as well.
As far as developments, I discovered an anomaly that quite possibly has been giving me grief since the beginning...at least in my testing environment.
Turns out the REST Request which was designed to retrieve the listing of all virtual wires was incomplete and needed to be appended with the following Query Parameter: ?startindex=0&pagesize=1024. The discovery revealed that the default output (w/o the query parameters) is limited to one (1) page only. This equates to roughly 20 virtual wires per page. My testing environment had double that amount. You would think the reverse would apply by default. Maybe an issue for the API specialists in VMware to rectify..? 😉 For info, 1024 is the maximum amount of page returns that can be specified in a request. Long story short, this would appear to explain the inconsistent results and the many "undefined" errors I was getting via the output throughout my testing.
Although this was a difficult issue to troubleshoot, in the end and much to your credit, I was able to narrow the scope and isolate the true source of the problem. After applying the query change as well as a few "other" necessary changes, the original script and code functioned as intended.
Despite what was discovered, I decided to re-engineer the entire script using all your input and methodology since there was considerably much more value! I liked the how you re-tooled the search features and incorporated a number of checks/logging at various stages, the ability to convert things to a JS 'Object' type and back to a string for further validation, and finally the introduction of the various "functions" and how to invoke them. All new processes to me which helped fast-track this issue immensely!
Suffice it to say, your assistance allowed me to acquire much more insight into JS and effectively apply your logic to my use cases. I'm a Systems integrator by trade with virtually no programming experience, so this has been an eye opener to say the least..
All the accolades aside, I am very grateful once again for your help. Can't thank you enough!
Ron
Hi
Sorry, I've not had the time to log in for ages 🙂
No problem at all, just glad I could help