Pls little help with JSONPath

I have mqtt tasmota device which is sending three different JSONS into one topic which I need to monitor
one format is:

{"Time":"2024-01-12T19:19:27","TuyaSNS":{"Temperature":21.0,"TempSet":30.0},"Thermostat1":{"ThermostatModeSet":1,"TempTargetSet":18.00,"CtrDutyCycleRead":44,"ControlMethod":0,"HybridControllerPhase":1,"EmergencyState":0},"TempUnit":"C"}

second:

{"TuyaSNS":{"TempSet":31.0}}

third:

{"TuyaSNS":{"Temperature":27.0}}

This is thermostat, which first is periodic state published automatically, second is when physical button on the device is pressed and third is when internal temperature is changed. And this is published by tasmota itself.
What I need tho, is to catch TempSet from the device and use it as tempset for tasmota internal thermostat. :wink:

To avoid a lot of parsing errors in logs while I was doing parsing on incomming MQTT payload in things.file I’d like to use rule.

So i’ve done item which stores whole json. and then got testing rule

rule "Wellness floor temperature"
when
    Item Wellness_Temperature changed or
    Item Wellness_Heating_Json changed
then
    val String json = (Wellness_Heating_Json.state as StringType).toString
    val String type = transform("JSONPATH", "$.TuyaSNS._type", json)

	if (type == "Temperature") {
        
		val String temperature  = transform("JSONPATH", "$.TuyaSNS.Temperature", json)
        
        Wellness_Heating_Temp.sendCommand(temperature)
    }
    if (type == "TempSet"){
        
        val String tempset  = transform("JSONPATH", "$.TuyaSNS.TempSet", json)

        Wellness_Temperature_Set.sendCommand(tempset)
    }
    
end

But type is never populated with proper Strings, it’s always full json for some reason

when I’m trying this approach

    val String temp = transform("JSONPATH", "$.TuyaSNS.Temperature", json)
    val String set = transform("JSONPATH", "$.TuyaSNS.TempSet", json)

    logInfo("x",temp)
    logInfo("z",set)

That works if first format arrives.
if second or third, one of the variables holds whole json again instead being empty.

2024-01-12 19:24:58.564 [INFO ] [org.openhab.core.model.script.x     ] - {"TuyaSNS":{"TempSet":35.0}}
2024-01-12 19:24:58.564 [INFO ] [org.openhab.core.model.script.z     ] - 35.0

Is that expected behaviour?
Can it be done somehow dynamically? or is there a better way how to get value from these?
I do like first approach, but can’t get that example from here JSON Handling in rules? working.

Thanks

That’s what the REGEX filter with chaining is for. You can define a REGEX that looks for something that only appears in the messages for a given topic. All other messages will be ignored.

REGEX:(.*TempSet.*)∩JSONPATH:$.TuyaSNS.TempSet
REGEX:(.*Temperature.*)∩JSONPATH:$.TuyaSNS.Temperature

Processing JSON is going to be much easier in a JS rule.

There is no element _type in any of the three JSON elements you show above. I am not super knowledgable on JSONPATH but I do know that the JSONPATH transformation does not support everything that JSONPATH can do. I would not be surprised if that’s one of them.

With the exception of REGEX (see above), when a transform fails the full untransformed String is what gets returned.

So far this seems expected behavior. When {"TuyaSNS":{"Temperature":27.0}} arrives, there is no $.TuyaSNS.Temperature found so the transformation returns the full String.

Yes.

Your best choice is to use the REGEX chained to the JSONPATH transform as shown above and forget about the rule.

If you insist on using a rule, I’d recommend using a JS rule so you can use native JSON processing instead of the transform.

var parsed = JSON.parse(event.itemState);
if(parsed.TuyaSNS.Temperature !== undefined) {
  items.Wellness_Heating_Temp.sendCommand(parsed.TuyaSNS.Temperature);
}
if(parsed.TuyaSNS.TempSet !== undefined) {
  items.Wellness_Temperature_Set.sendCommand(parsed.TuyaSNS.TempSet);
}

To stay in Rules DSL, you’ll basically need to use REGEX first to test to see which message you got anyway so you are not really saving anything over using transform chaining. Maybe you can run the JSONPATH and see if you get back the same String to avoid the REGEX.

good thinking, totally forgot about REGEX :wink: thanks for kicking the old tire.
I’m not insisting on anything, always learning better ways.

Thanks and hats down as always for your complex answers!