According to https://stackoverflow.com/questions/20804163/check-if-a-key-exists-inside-a-json-object :
myJsonObject.hasOwnProperty('somekey')
will tell you if myJsonObject has that key itself
myJsonObject["somekey"] will return false if the key does not exist,
or if its value evaluates to false for any reason
Both of these are returning errors if “somekey” is not a key in my json object. Eg:
server.log("JSON: " + myJsonObject); // JSON: {"error": "stalled"}
if( myJsonObject.hasOwnProperty("rpms") ) // error, won't compile
if( myJsonObject["rpms"] == false ) // compiles, throws error at runtime
What I’m trying to do:
When an IMP sends data to the server, I’d like to reply to the imp with either an error message or a reading, so options would be {“error”: “stalled”} or {“rpms”: 3000}
I had an idea for a workaround that would involve adding a “status_type” key, so it would be like {“status”: 0, “error”: “stalled”} or {“status”: 1, “rpms”: 3000} but later down the road I’d like to have more complicated scenarios that may have a list of optional pieces of information I’m trying to send to the imp, and I don’t want a status code for every possible combination
If you’re exchanging data between the device and the agent, you don’t need to use JSON, which is a serialised string of objects that you can define in squirrel. Just pass the object directly.
In your device, you can use:
agent.send("myData",{ result=100 })
agent.on("myResponse",function(response) {
if ("error" in response)
server.log("Error:"+response.error) // table.key syntax works
else
server.log("RPMS"+response["rpms"]) // table["key"] syntax works too
})
and in your agent you can use:
device.on("myData",function(response){
if ("result" in response) // use "in" to test for presence of field within table
device.send("myResponse",{ rpms=3000 })
else
device.send("myResponse",{ error="stalled" })
})
To clarify, Squirrel and the imp API lack the JavaScript .hasOwnProperty() method. Instead, you use the in
keyword as demonstrated by @coverdriven’s code:
if ("rpms" in myJsonObject) { . . . }
Note that that syntax assumes rpms is a string — Squirrel table keys need not be, but for non-strings you use this syntax:
if (myJsonObject[false] == "negative") { . . . }
You can use the same with strings, as you do in your // compiles, throws error at runtime
line:
if (myJsonObject["rpms"] == 42 ) { . . . }
However, yours is failing because, in Squirrel, a missing key returns null
not false
.
To summarize, use
if (!("rpms" in myJsonObject)) { server.log("Key 'rpms' missing"); }
@smittytone,
Squirrel isn’t like Javascript in this respect:
if (myJsonObject["rpms"] == null) { server.log("Key 'rpms' missing"); }
indexing a table with a nonexistent key always raises an exception. The only way to safely test it is with “in”
and I think you meant:
if (myJsonObject[false] == "negative") { . . . }
in your second example
Good point, @coverdriven. I was sure I’d used that in code in the past, but you’re right, it fails. Comment amended accordingly.