Trying to parse HTTPGet returned JSON

Hi,
I am a novice to Groovy and I am trying to parse a JSON returned from HTTPGet sent to Nuki Lock with no success.
I saw a similar question, but the answer provided there didn't help.

Here is the code I am running:
def params = [
uri: "https://api.nuki.io/smartlock/",
headers: [Authorization: "Bearer ${settings.Token}"],
contentType: "application/json",
textParser: true
]
try {
httpGet(params) { resp ->
if (resp.success) {
def slurper = new JsonSlurper()
def json = slurper.parseText(resp.data)
log.debug "show: ${json}"
}

I get an error:
Call to lock failed: No signature of method: groovy.json.JsonSlurper.parseText() is applicable for argument types: (java.io.StringReader) values: [java.io.StringReader@5665c2]

resp.data contains the following:
[{"smartlockId":179934536868,"accountId":757913452,"type":4,"lmType":0,"authId":3431650,"favorite":false,"config":07-05T18:03:40.801Z" .....}]

My end goal is to place the smartlockId value in a variable.
Thanks,
Avi

Remove textParser: true and it'll probably return your JSON response already parsed into a Map (that is, no need to use JsonSlurper, unless it is still returned as a string).

2 Likes

I try to avoid using httpGet and use asyncHttpGet instead....

httpGet consumes resources since it's an inline call.

async is just that.. the http is sent and only when the response arrives, does that handler get called. The hub is free to do everything else in the interval.

	asynchttpGet("getStatusHandler", params)
}

def getStatusHandler (resp, data) {
	try {
		if (resp.getStatus() == 200 || resp.getStatus() == 207) {
			Map setStatusResult = parseJson(resp.data)
		}

The above is a snippet of what I use... and don't need the slurper lines.

2 Likes

If you really need to use the textParser option for some reason, then you'll need to read characters from the StringReader into a char buffer and then create a string from that before parsing with JsonSlurper.

https://docs.oracle.com/javase/7/docs/api/java/io/StringReader.html#read(char[],%20int,%20int)

1 Like

thanks @tomw . Removing textParser did the trick.
I published the driver for everyone to use: https://github.com/avigrabinsky/Hubitat-Nuki-Lock

1 Like

Thanks @csteele . Since the code runs only when "Save preferences" is clicked, it doesn't matter much that it is synchronous. But I appreciate your feedback!

I feel I didn't explain it well then :smiley: The point of Async is to allow the hub to do something, anything in that half second between the hub sending and the response being returned. Or maybe certain busy moments out there on the internet, the response is delayed and the time between send and receive is 1 second... or 10. Whatever the interval, Sync means the hub is waiting, in a wait loop, for the result. With Async, the hub instantly carries on with its ZWave and Zigbee work and when the result eventually does arrive, it runs the handler.

"it doesn't matter much" might easily be true, but I also feel like I didn't explain it well.

I've had to make the same choice myself in a driver that does a login.

1 Like

Thanks @csteele ! I will add it on next improvement cycle.

Don't let me twist your arm.. :smiley: If sync is better to the flow of the app/driver, then so be it. I just want to be clear on why in the world there are two, sync and async. In a way, async adds to a more "real time" response. The Hubitat platform is NOT a RTOS (RealTimeOperatingSystem) but the closer one gets to 'interrupt (event) driven' the closer it simulates one. :smiley: