It seems like this should be relatively simple, but apparently not so much. I can't figure out for the life of me how to store strings and integers in an array in GWT. What data type do you use? If I use JsArrayString, it throws an IllegalArgumentException when retrieving an index containing a number. I obviously can't use JsArrayInteger (I have strings). JsArray requires a type, of which I have no idea what to use (if it can be used), I've tried String but get the same results.
The data being retrieved is from a script page and it does not have the ability to distinguish between strings and ints (ColdFusion).
Now this is possible using JsArrayMixed.
I think you can use Object as your type. You'll have to box your primitives (int) in the Integer class if it doesn't do it automatically for you. You will also have to do some type checking after you grab what's in the array.
It's kinda clunky, but you could always do some brute-force determinations of whether a given value is an int or string:
<cfset val1="one">
<cfset val2="1">
<cfif int(val(val1)) eq val1>int<cfelse>string</cfif>
<br />
<cfif int(val(val2)) eq val2>int<cfelse>string</cfif>
This should give you
string
int
GWT does not currently have the functionality to parse an array structure that contains two different types of data unless in strict JSON form (not as part of a JSON structure in an array passed from ColdFusion apparently).
Related
I'm trying to retrieve Firebase data with Polymer Fire. When I look in the console it's returning two objects, however the length of the array is three. When I'm trying to execute a dom-repeat I'm successfully printing two filled in rows but also one empty row. How is this possible?
Firebase stores data as associative arrays, essentially a dictionary of key/value pairs.
That means that in order to deal with arrays, it converts an array to a dictionary when you store it and then back to an actual array when you read it. Here you are getting bitten by the SDK converting your non-array into an array by padding it with a leading element.
If you don't want the SDK to do this conversion, the easiest way is to store the items with a non-numeric key, e.g. "item1", "item2".
Read more about how Firebase deals with arrays in this classic blog post: https://firebase.googleblog.com/2014/04/best-practices-arrays-in-firebase.html
This is a follow up question to: Append to JSON array with ColdFusion, taking Null values into consideration?
That question was answered yesterday and worked perfectly (Thank you Kevin B. and Leigh!). However, the application I am pulling my JSON data from threw me a curve ball this morning. Sometimes, depending on the data I am requesting, it returns the entire JSON as an array like this:
[
{
"loginHosts": [
"server1.example.com"
],
"sudoHosts": [
"server1.example.com"
],
"CPG": [
"my_group"
],
"mail": "myuser#example.com",
"loginShell": "/bin/bash"
}
]
I don't know why that application does this. If I knew this was a possibility I would have added that information to my previous question, my apologies.
My attempts to find a solution lead me here first: Using JSON Data with Coldfusion . Looping over the JSON array as a collection seemed to work, but only if none of the array values were Null. I thought using this code, as in the previous question, would work if I used it for all the JSON fields:
<cfif NOT structKeyExists(myStruct, 'sudoHosts') OR NOT isArray(myStruct.sudoHosts)>
<cfset myStruct.sudoHosts = []>
</cfif>
This was not the case. I continually get:
Error: Can't cast Complex Object Type Array to String
Looking through the debug output, Lucee did throw this out: string Use Built-In-Function "serialize(Array):String" to create a String from Array. I did more digging and found this article: Railo tip: store complex data by using serialize(data). Sadly, Null values have struck again. Also, my understanding is serialize() is similar to evaluate(), and not recommended.
I will continue looking for a solution but any help is, as always, greatly appreciated!
-- EDIT --
I came across this thread: ColdFusion JSON object vs array of objects. I noticed the JSON in the question is an ARRAY [], and I applied the answer to my code, but am still running into the Null problem. I guess I don't know how to check for nested Null values. :(
Take it one step at a time.
Ideally you should determine why the response differs. Since you say those differences usually correspond to something different in your request, that strongly suggests you may be overlooking (or possibly misunderstanding) something in the remote API. I would recommend re-reviewing the API to identify that "something", in order to figure out the right approach. Otherwise, the code will quickly become unmanageable and inefficient as you continue to tweak it to handle each "new" situation.
If for some reason the API truly is returning different results without a valid reason, the best you can do is to code according to what you expect and fail gracefully when you receive something else. Start by listing the expected possibilities:
Response is a single structure containing certain keys OR
Response is an Array of structures containing certain keys
Based on the above, you can use the IsArray and IsStruct functions to determine the format of the response, and handle it accordingly. First examine the deserialized object. If it is an array, extract the structure in the first element (Note, I am assuming the array only contains a single element, as in the example. If it can contain multiple elements, you will need additional handling).
<cfset data = deserializeJson(originalJSON)>
....
<!--- Extract structure from first element of array --->
<cfif IsArray(data) && arrayLen(data)>
<cfset data = data[1]>
</cfif>
Next verify you are now working with a structure, containing the expected key(s). If so, go ahead with your usual processing. Otherwise, something unexpected happened and the code should perform the appropriate error handling.
<!--- Verify object is a structure and contains expected key(s) --->
<cfif IsStruct(data) && structKeyExists(data, "loginHosts")>
... process data as usual
<cfelse>
... data is not in expected format, do error handling here
</cfif>
The above is a very quick and dirty example, but should demonstrate the basic idea. As long as you are certain you are using the API correctly, all you can do is code for the expected and fail gracefully when something different happens.
Here is Google calendar data retrieved from https://www.googleapis.com/calendar/v3/users/me/calendarList.
The response is in JSON, so I used the ColdFusion method deserializeJson to turn it into a CFML structure.
I cannot figure out the syntax to loop over this data. You'll see that within the CFML struct, 'items' is an array of calendars returned from Google, and every attempt to access the array within the struct generates a Java string conversion error or a syntax error, likely because I can't get the syntax correct.
Any help is very appreciated, thanks very much
Some trial and error will help - you are already on your way. The root object you dumped out already but we'll do it here to represent the object you dumped out as "obj":
<cfset obj = deserializejson(googleCal)>
The first level is a struct so you would address them as follows:
#obj.etag# // this is a string
items contains an array. So you have items[1-n] ... however many are in the array. This code would set myArrayObj as an array with 3 items (based on the dump above).
<cfset myArrayObj = obj.items>
You can verify using isArray:
#isArray(myArrayObj)#
Each array member contains a struct in turn so you can output:
#myArrayObj[1].accessRole# // this would be a string
... And so on. Make a note that index item 3 in the array is a blank struct so you need to "check" to see if the struct is empty before you work with it's keys. Investigate "structKeyExists()" for that purpose.
If you want to deal with each of the "items" in a loop (a pretty typical choice) you would simply do a cfscript loop or cfloop using array as in:
<cfloop array="#myArrayObj#" index="i">
<cfif structKeyExists(myArrayOb[i], "accessRole")>
#myArrayObj[i].accessRole#
</cfif>
</cfloop>
Hope this helps. Good luck!
I want to compare two arrays of objects.
but there is not suitable method found for that method since it doesnt accept objects other from String, Integer etc..
I already override Equals method on the objects of the array.
But how do i pass the array to the method?
Assert.assertArrayEquals(esperado.getListaEquiposTorneo(), resultado.getListaEquiposTorneo());
//esperado.getListaEquiposTorneo(), resultado.getListaEquiposTorneo()) list 1 and 2 of objects made by me
First, you should be able to just use assertEquals
Assert.assertEquals(esperado.getListaEquiposTorneo(),
resultado.getListaEquiposTorneo());
I prefer to use Hamcrest as it gives better error messages
assertThat(actualArray,
IsArrayContainingInOrder.arrayContaining(
expectedArray));
assertThat(resultado.getListaEquiposTorneo(),
IsArrayContainingInOrder.arrayContaining(
esperado.getListaEquiposTorneo()));
IsArrayContainingInOrder
See Tomasz Nurkiewicz answer:
ArrayUtils.isEquals() from Apache Commons does exactly that. It also handles multi-dimensional arrays.
you can use a simple AssertTrue on the result
I have some data in an integer[] Native Array and I want to perform ArrayAppend / ArrayDeleteValue operations on it. I've noticed that this fails silently in Railo 3.3 because the native array types are fixed length (you can change values but not add/remove).
The question is can I convert a native array to a regular coldfusion/railo array object without doing iteration on it? Is there some kind of built-in function/method for this or do I have to write my own?
I found one way. railo_array = ArrayMerge([], my_native_array). Not sure if there's a better way.