You access objects by key and arrays by index. Hence order of keys in object is not necessary (and not guaranteed in javascript). Said another way, the value of “oProblem.id” is always returned no matter the order “id” shows up as. Conversely, “oProblem[0]” is never used to get the value of the first key in an object.
Example of iterating objects in Servoy:
/**
* @properties={typeid:35,uuid:"BD1E4BB4-F1B1-48C5-81BB-1571CD142A5B",variableType:-4}
*/
var myObjectSimple = function() {
return {
a: 1,
b: 2,
c: "3"
}
}
/**
* @properties={typeid:35,uuid:"F1E8AC6B-6884-44C3-9C58-6A4B1ED7CB54",variableType:-4}
*/
var myObjectClosure = function () {
// total up all numbers with startValue
var aggregate = function (inputArray, startValue) {
// inputArray is Array?
if (Array.isArray(inputArray)) {
inputArray.filter(function(item) {
return typeof item === "number"
})
.map(function (item) {
startValue += item
})
}
return startValue
}
return {
a: 1,
b: 2,
c: "3",
calc: aggregate
}
}
/**
* USAGE: #1 processObject(myObjectSimple) // output order not guaranteed
* -> a: 1.0
* -> b: 2.0
* -> c: 3
* #2 processObject(myObjectClosure) // w/method on the object
* -> a: 1.0
* -> b: 2.0
* -> c: 3
* -> calc: 3.0 // result of object "api" method
*
* @properties={typeid:35,uuid:"C142B794-16A4-4D8E-9DC5-A64F6C690B3A",variableType:-4}
*/
var processObject = function (factoryFN) {
var newObject = factoryFN()
// Iterate object version #1
// if (typeof newObject[prop] === "function") {
// var sum = newObject[prop]([newObject.a, newObject.b, newObject.c], 0) // example of calling newObject.calc(...) at the destination
// application.output(prop + ": " + sum)
// }
// else {
// application.output(prop + ": " + newObject[prop])
// }
// Iterate object version #2 (preferred)
Object.keys(newObject).forEach(function (prop) {
if (typeof newObject[prop] === "function") {
var sum = newObject[prop]([newObject.a, newObject.b, newObject.c], 0) // example of calling newObject.calc(...) at the destination
application.output(prop + ": " + sum)
}
else {
application.output(prop + ": " + newObject[prop])
}
})
Iterating objects in the browser (after calling your REST api endpoint for example) is similar (replace “application.output(…)” with “console.log(…)”)
bcusick:
Is there a way I can keep it in the order I’ve specified (so it will match my API schema)?
Is there a specific reason to keep it in order?
As David already mentioned the order has no effect on accessing the data since you need to access it directly by property name.
If it’s for display/document purposes you could keep an array with the property names in the correct order and iterate over that to fetch the values in order.
And as David already showed (although kinda buried in the code) you can get an Array with the property names of an object using the Object.keys(myObject) function.
Thanks guys! I know that the order doesn’t matter - I was just wondering if there was a way to “prettify” the output. I know that there is no guaranteed “order” when working with object properties… but I just wanted to make sure I wasn’t missing something really obvious.
David - I appreciate your in-depth explanation!
Robert - that’s the route that I was going to go down if all else failed.
bcusick:
Thanks guys! I know that the order doesn’t matter - I was just wondering if there was a way to “prettify” the output. I know that there is no guaranteed “order” when working with object properties… but I just wanted to make sure I wasn’t missing something really obvious.
Yea, nothing at the end of that hole. But on a closely related note, changing up your object structure slightly to include an array of keys is a useful pattern. You can still directly access a specific object value by key (one step further removed, ie myObj.items.key instead of myObj.key) and you iterate the additional array of keys to process the keys in order:
/**
* @properties={typeid:35,uuid:"33E547AA-6395-4EF9-8562-F1A6E6BB5301",variableType:-4}
*/
var myObjectOrdered = function() {
return {items: {
a: 1,
b: 2,
c: "3" },
itemsOrder: ['a', 'b', 'c']
}
}
/**
*
* USAGE: processObjectOrdered(myObjectOrdered) // output order guaranteed
* -> [ 1.0, 2.0, 3 ]
*
* @properties={typeid:35,uuid:"9C49ECBB-A2AA-461A-AB39-33FD0530DBE5",variableType:-4}
*/
var processObjectOrdered = function(factoryFN) {
var newObject = factoryFN()
var sampleOutput = []
// Iterate array and use to access object keys
if ( newObject.hasOwnProperty('itemsOrder') && Array.isArray(newObject['itemsOrder']) ) {
newObject['itemsOrder'].forEach(function(value) {
sampleOutput.push(newObject['items'][value])
})
}
application.output(sampleOutput)
}
For example if you’re passing back functions instead of scalar values you could execute those functions in order and just choose a specific function to execute.
a bit late on this, but with JSON, order isn’t important (general) as others have mentioned. If you need to return things in a certain order, then you’ll need to use an array in the JSON. Then the order is kept.
Scott - WHOA! That’s really awesome! THANK YOU for that tip!
I was really just trying to see if I was missing something - but as long as I write docs that are clear - and document all the properties, datatypes, etc - it should be usable.
As this is my first stab at an API - I just didn’t want to “Bob-ify” it and screw the pooch.