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!