JSON Parsing in Device Type Handler

I have an arduino node in my garage that I had been using with HomeGenie. It parsed the simple JSON string in C# no problems. I haven’t had much time to get it working with SmartThings yet but I keep having trouble parsing the JSON. I validated the JSON string with a couple online utilities.

The DTH is getting the JSON string into the msg.body but not parsing it automatically into msg.json so I tried to add JSON.parse…
//msg.body={“door1”:“0”}
var j = JSON.parse(msg.body);
log.debug “j.door1 ${j.door1}”

This keeps giving NULL pointer. Does the arduino server have to report “Content-Type: application/json”?

If I try this it fails…
var j = JSON.parse("{“door1”:“0”}");
log.debug "j.door1 ${j.door1}"
until I escape the JSON required quotation marks, then fails for NULL again.

Any ideas? Pointers to ST documentation for JSON parsing? Thanks in advance!

You will need to include the jsonbuilder or jsonslurper library. Instead of var use def in groovy

http://docs.smartthings.com/en/latest/cloud-and-lan-connected-device-types-developers-guide/building-lan-connected-device-types/building-the-device-type.html?highlight=json#parsing-the-response

Here are two examples: http://groovyconsole.appspot.com/script/5205729338195968

Click “Edit in Console” then execute. Hopefully this will help get you started.

3 Likes

This should work in ST IDE

def str = '{"door":"1"}' 
def results = new groovy.json.JsonSlurper().parseText(str)  
log.debug("Door: ${results.door}")​
2 Likes

I believe that the message returned from your device needs to have a Content-Type: application/json header in order for it to be parsed automatically into msg.json (I assume you use def msg = parseLanMessage(message) in the beginning of your parse(String message) method?

1 Like

I updated my arduino device to report the content-type and I have simplified the Groovy parse down to…

def parse(String description) {
def msg = parseLanMessage(description)
}

Chrome shows this in the browser:

{“door1”:“1”}

In chrome ctrl-shift-i I see this response header now:

HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 122
Connection: close
Access-Control-Allow-Origin: *

But IDE now reports error:

java.lang.NullPointerException: Cannot invoke method getDataValue() on null object

I added a try/catch/log around the parseLanMessage but then nothing prints at all :frowning: confused

{"door1":"1"} doesn’t match Content-Length: 122 header (it should be Content-Length: 13 instead). Are you sure you are sending the correct Content-Length from your Arduino sketch?

Sorry… I trimmed some extra data out of the JSON string to keep it simpler in the forum here. I think the ESP8266 library is adding that, I just send with…

ESP8266WebServer server(80);
server.send(200, “application/json”, webString);

Thank you for the help!

Yes - you are correct, ESP8266WebServer set the Content-Length correctly. I use the same for posting JSON to ST and it works just fine for me.

Are you sure that your full JSON is valid (try an online validator)?

Here is the beginning of my parse() method which is working correctly for me:

def parse(String description) {
  def msg = parseLanMessage(description)
  def bodyString = msg.body
  if (bodyString) {
    def json = msg.json;
    if (json) {
      log.debug("Values received: ${json}")
      // access the json here and do whatever you need…
    }
  }
}

I pasted the JSON from browser into a validator a few weeks ago since my device is behind firewall. I think I am having problems before the parse now; debug at the top of it doesn’t print. I need to figure out the flow through these. Also I try adding a device from IDE and it is accepted. On my phone app, I add the device but it is failing now, nothing shows in the “Garage” room… just “Error loading things”. This was working before and I was able to add tiles for the various sensors I plan to have working.

Does the device have to be added into phone app to work from IDE debugger? The device type is compiling ok and I add the device in IDE. So after I publish, and select location home, it shows in the list of devices to test with. it all seems same as a couple weeks ago when I did see the JSON string in log (I just could get it to parse). Now it seems to be failing before that.

Do you have your device network ID set correctly? either IP:Port (in hex) or MAC address (which typically is the better choice)

Chrome has a json parser plugin that I used for debugging when getting a json return from the particle photon.

How are you communicating with the device? You mentioned that it is behind the firewall, but ALL smartApps execute in the SmartThings cloud. My guess is you are trying to call an local endpoint and its not resolving giving you the null.

For local calls you will need to use hubAction

http://docs.smartthings.com/en/latest/cloud-and-lan-connected-device-types-developers-guide/building-lan-connected-device-types/building-the-device-type.html#making-outbound-http-calls-with-hubaction

Looks like I am using hub action, I started with the ESP8266 Contact Sensor code. I am reverting back to it again to see where I went astray because I was getting data from my device at one point. Probably won’t have time to work on it again until after the weekend. Thank you all again!

Try this: json formatter https://jsonformatter-online.com