Get value from JSONPATH to Item

Hello,

I would like to fill an Item Number from a JSON return. When saving my item, I get no errors. Also, my JSONPATH is valid against online test tools. JSONPATH is installed via Paperui.

Item:

Number	Hue_Brightness_Woonkamer			"Brightness [%s]"		(gWoonkamer)	{ http="<[http://192.168.1.203/api/<myapiusername>:10000:JSONPATH($.groups[?(@.name=='Woonkamer')].action.bri)]" }

The return (on test tools):

[
	123
]

I get no errors in openhab.log, am I doing something wrong?

1 Like

@bastiaan_van_h

  1. Please also post your whole json exprression!
  2. What error do you get? A Question like yours, expects someone who want’s to help to guess a lot.
  3. I think a number needs a floatingpoint formatter not a string.
"Brightness [%f]"	

@Josar, thank you for taking the time to reply.

  1. I didn’t thought that was relevant because my JSONPATH is valid. I wil post it below.
  2. As described, I get no errors in openhab.log. Are there perhaps any debugs I can enable regarding JSONPATH and/or HTTP get?
  3. I’ve changed it to decimal and floaingpoint, it doenst seem to make a difference. I would expect an update in the servicebus once the value is changed.

JSON:

{  
   "groups":{  
      "1":{  
         "name":"Woonkamer",
         "lights":[  
            "13",
            "8",
            "6",
            "12",
            "5",
            "4",
            "7",
            "9",
            "3"
         ],
         "type":"Room",
         "state":{  
            "all_on":true,
            "any_on":true
         },
         "recycle":false,
         "class":"Living room",
         "action":{  
            "on":true,
            "bri":123,
            "hue":0,
            "sat":0,
            "effect":"none",
            "xy":[  
               0.4541,
               0.3990
            ],
            "ct":384,
            "alert":"none",
            "colormode":"xy"
         }
      }
   }
}

@bastiaan_van_h sorry did not read it properly, thought you wrote i get an error. :sweat:

Does one of those work? So does the http binding return something?
When you use this, at least something should apear int the log when Hue_Brightness_Woonkamer changes. I changed it to a string for testing and removed the json querry.

String Hue_Brightness_Woonkamer "Brightness [%s]" (gWoonkamer)	{ http="<[http://192.168.1.203/api/<myapiusername>:10000" }

Did you install the JSONPATH transformation?
http://<YOUR_IP>:8080/paperui/index.html#/extensions

Does the JSONPATH return valid values when searched?

String Hue_Brightness_Woonkamer "Brightness [%s]" (gWoonkamer)	{ http="<[http://192.168.1.203/api/<myapiusername>:10000:JSONPATH($.groups.1.name)]" }

Maybe you also need to install the HTTP binding.

You use a transform not a binding.

Try looking over this working rule of mine.

rule "Milight_ID1_G1_HubStates"
  when
	Item Milight_ID1_G1_EspMilightHub changed
  then
	var sJSONBLOB = Milight_ID1_G1_EspMilightHub.state.toString
	var sMODE =	transform("JSONPATH","$.bulb_mode", sJSONBLOB)
	var sSTATE=	transform("JSONPATH","$.state", sJSONBLOB)
	var sLEVEL=	transform("JSONPATH","$.level", sJSONBLOB)
	var Number iLEVEL= Integer::parseInt(sLEVEL).intValue //convert the string to an int.
	
	if(Milight_ID1_G1_State.state!=sSTATE)
	Milight_ID1_G1_State.postUpdate(sSTATE)
	
	if(sMODE=="white") // Code to handle a white JSON blob
	{
		var sCTEMP=transform("JSONPATH","$.color_temp", sJSONBLOB)
		var iTempScaled=(((Integer::parseInt(sCTEMP)/2.17)-171)*-1).intValue //Dirty but seems to work. Converts string to int and scale range.
		Milight_ID1_G1_CTemp.postUpdate(iTempScaled) //send CT to globe
		Milight_ID1_G1_Brightness.postUpdate(iLEVEL) //send new brightness to globe
	}
	
	else if(sMODE=="color") // Code to handle a colour JSON blob
	{		
		var String sHUE			= transform("JSONPATH","$.hue", sJSONBLOB)
		var String sSATURATION	= transform("JSONPATH","$.saturation", sJSONBLOB)
		Milight_ID1_G1_Brightness.postUpdate(iLEVEL) 	//update main dimmer item
		Milight_ID1_G1_Hue.postUpdate(sHUE+","+sSATURATION+","+sLEVEL)		//update color item      
	}
end

Thank you @bweekers for this, I did not have the HTTP binding installed. Despite I used it in my item without HTTP binding installed, I did not generate any error. After installing I now get returns.

After digging, I found out that the search part of my JSONPATH query does not work in Openhab.

Does not work:

$.groups[?(@.name=='Woonkamer')].action.bri

Does work:

$.groups.1.action.bri

I would like to include a search, because when in the future I can have more groups. Any idea why my search query isn’t working in Openhab?

You are using an indefinite path in your JSONPATH, which will return a List, not a string. Indefinite paths can’t be used in JSONPATH for Items/Labels, and take special handling in rules.

There was a relatively recent ESH PR to resolve an issue that has made its way into the OH snapshot build, where the first element of the List would be returned, if there is only one element in it. There are some unfortunate side affects to this that I am hoping will be addressed.

To resolve your issue, you could update OH to the snapshot, or use a JS transform to parse the JSON.

@bastiaan_van_h

I think a query will always return as an array. And an Array can not be parsed to a Number.
Try to change your Item to a string. There should be a string in the Item.state which looks like [123]

One solution would be to use a rule and a proxy item, or use a javascript transformation and do the jsonpath query there, strip of the bracket and return the value.

Number Hue_Brightness_Woonkamer "Brightness [%s]" (gWoonkamer)	{ http="<[http://192.168.1.203/api/<myapiusername>:10000:JS(jsonpathQuery.js)]" }
 /etc/openhab2/transform/jsonpathQuery.js
not sure what to put here

But also there seems to be an issue with the jsonpath transformation when used in rules.

rule "test"
  when
    Item Test_1 changed 
 then
    var test = "{  
      \"groups\":{  
          \"1\":{  
            \"name\":\"Woonkamer\",
            \"action\":{  
                \"bri\":123 
        }}}}"

    var String test1 = transform( "JSONPATH",
                          "$.groups.1.action.bri",
                          test )

    var String test2 = transform( "JSONPATH",
                          "$.groups[?(@.name=='Woonkamer')].action.bri",
                          test )

    logInfo("Test",   test.toString ) 
    logInfo("Test 2", test1.toString ) 
    logInfo("Test 3", test2.toString ) 

 end
[INFO ] [smarthome.event.ItemStateChangedEvent] - Test_1 changed from ON to OFF
[INFO ] [g.eclipse.smarthome.model.script.Test] - {
      "groups":{
          "1":{
            "name":"Woonkamer",
            "action":{
                "bri":123
        }}}}
[INFO ] [eclipse.smarthome.model.script.Test 2] - 123
[INFO ] [eclipse.smarthome.model.script.Test 3] - []

Edit: see @5iver post.

Try with a deep scan… $..[?(@.name=='Woonkamer')].action.bri

Or $.groups.1[?(@.name=='Woonkamer')].action.bri

@5iver jeah both are working.

But whats the difference and why does the first one not work.
So Basically it returns [123] which is expected but also does not solve the problem at hand of @bastiaan_van_h.

And why does the the first one work with

http://www.jsonquerytool.com/

So a working rule could look like this.

rule "test"
  when
    Item Test_1 changed 
 then

    // filter applied on proxy item
    var test1= transform( "JSONPATH",
                          "$..[?(@.name=='Woonkamer')].action.bri",
                          Test_1 )

    logInfo("Test ", test1.substring(1, test2.length-1) ) 
    // Strip off the brackets and 
    // Post result to Number Item
    Test_2.postUpdate( test2.substring(1, test2.length-1) )
 end

The way I understand it, $.groups[?(@.name=='Woonkamer')].action.bri searches the children of groups, and there is no child of “groups” with key “name”. But $.groups.1[?(@.name=='Woonkamer')].action.bri has a child with key “name”, so it is found. The deep scan (recursive descent) searches the whole tree, so also finds “name”.

Correct. His issue should be solved by what I posted earlier. I just saw your reply and thought I’d try to help. You hadn’t found an issue with using the JSONPATH transformation in rules… the expression you were using just wasn’t returning a result. But read through the issue I linked… as written, there are definitely some things that can be improved!

Jayway (used by OH) is a Java port of Goessner, so there could be differences. There could also be differences in the versions. Sorry… nothing definitive. :smile:

@5iver Thanks, i missed that there was one branch missing, just thought when the online test proceeds it should be good.

Hello @Josar and @5iver, thank you both for your analysis.

So my JSONPATH query returns a list, and that’s why it isn’t catched by OH. I will perform the rule tests @Josar proposed and will come back with the result.