Transform JSON without quotes

Tags: #<Tag:0x00007f1865424aa8>

Hi,
So I have a JSON string without the quotes surrounding the strings that I need to transform to get a value.
Here is the string:

{binding_cmdrepollperiod=1500, doorlock_timeout=0, usercode_label_6=Kathy, group_1=["controller"], usercode_label_2=Abi, action_reinit=false, usercode_code_20=, usercode_code_16=, usercode_code_17=, usercode_code_18=, usercode_code_19=, action_failed=false, action_remove=false, binding_pollperiod=86400, usercode_code_7=, action_heal=false, usercode_code_8=, config_1_1=1, usercode_code_9=, config_2_1=255, usercode_label_1=Milo, usercode_code_3=123456, usercode_code_4=, usercode_code_5=, usercode_code_6=123456, config_7_1=30, usercode_code_12=, config_8_1=0, usercode_code_13=, usercode_code_1=123456, usercode_code_14=, usercode_code_2=640621, usercode_code_15=, config_3_1=50, config_4_1=5, config_5_1=1, usercode_code_10=, node_id=15, usercode_code_11=}

I have this JSON string stored in an item.
I am trying to get a name from
usercode_label_1
using
val strUser = transform("JSONPATH", "$.usercode_label_1", LFD_Config.state)
However I keep getting this error:

17:07:29.837 [ERROR] [untime.internal.engine.RuleEngineImpl] - Rule 'LFD Test': An error occurred during the script execution: Could not invoke method: org.eclipse.smarthome.core.transform.actions.Transformation.transform(java.lang.String,java.lang.String,java.lang.String) on instance: null

I am guessing the transform function is not able to find usercode_label_1 becasue it is searching for it with quotes around?

Is there any way to get around this if it is the case?

Thanks

Just to update the issue isnt actually with the quotes. I found they are there originally but getting dropped off somehow.
If I get the name direct from the http get it works like this:

rule "LFD Test"
    when
        Item LFD_Test changed // Just a test item to trigger the rule
    then
        val strStatus = sendHttpGetRequest("http://10.11.12.20:8080/rest/things/zwave:device:71bc65a0:node15")
        val strUser = transform("JSONPATH", "$.configuration.usercode_label_1", strStatus)
        logInfo("security.rules", "USER: " + strUser)
    end

Works!! :laughing:

But…

When I write this to an item, then read it from the item it then doesnt work :confused:

rule "LFD Test"
    when
        Item LFD_Test changed // Just a test item to trigger the rule
    then
        val strStatus = sendHttpGetRequest("http://10.11.12.20:8080/rest/things/zwave:device:71bc65a0:node15")
        val strConfig = transform("JSONPATH", "$.configuration", strStatus).toString
        LFD_Config.postUpdate(strConfig)
        val strUser = transform("JSONPATH", "$.usercode_label_1", LFD_Config.state)
        logInfo("security.rules", "USER: " + strUser)
    end

Any ideas?

Postupdate is asynchronous. Attempts to update then read back in the same rule are doomed to inconsistent failure.

There’s never a need to do that anyway, because you already know the value you just postupdated.

Ah - good to know… however, I only wrote that rule as an example.

The HTTP request and depositing of the string into the item are done at midnight every night.

Then during an action, my intention was to get the user from the item json string.

Okay, what’s the problem now?

JSON is like this:

TopLevel1
TopLevel2
  -Level2-1
  -Level2-2
TopLevel3
TopLevel4

When I run it though transform once to get all of Level2, it seems to take all of the surrounding quotation marks from the Level2 items.
Therfore I cannot run the Level2 string through the transform again to get the individual items.

Is this meant to be like that?

That’s not JSON. Can you elaborate a bit on “doesn’t work” maybe, with what you expected and what you got and what the rule looks like with the error fixed?

EDIT - JSONPATH does not and is not expected to output JSON.

Sorry, never meant that that was ‘JSON’. I just meant the structure I am using has two levels.

OK here is my JSON:

{
  "statusInfo": {
    "status": "ONLINE",
    "statusDetail": "NONE"
  },
  "editable": true,
  "label": "Z-Wave Node 015: YKFCON Smart Living Keyfree Smart Lock",
  "bridgeUID": "zwave:serial_zstick:71bc65a0",
  "configuration": {
    "binding_cmdrepollperiod": 1500,
    "doorlock_timeout": 0,
    "usercode_label_6": "Kathy",
    "group_1": [
      "controller"
    ],
    "usercode_label_2": "Abi",
    "action_reinit": false,
    "usercode_code_20": "",
    "usercode_code_16": "",
    "usercode_code_17": "",
    "usercode_code_18": "",
    "usercode_code_19": "",
    "action_failed": false,
    "action_remove": false,
    "binding_pollperiod": 86400,
    "usercode_code_7": "",
    "action_heal": false,
    "usercode_code_8": "",
    "config_1_1": 1,
    "usercode_code_9": "",
    "config_2_1": 255,
    "usercode_label_1": "Milo",
    "usercode_code_3": "111111",
    "usercode_code_4": "",
    "usercode_code_5": "",
    "usercode_code_6": "111111",
    "config_7_1": 30,
    "usercode_code_12": "",
    "config_8_1": 0,
    "usercode_code_13": "",
    "usercode_code_1": "111111",
    "usercode_code_14": "",
    "usercode_code_2": "111111",
    "usercode_code_15": "",
    "config_3_1": 50,
    "config_4_1": 5,
    "config_5_1": 1,
    "usercode_code_10": "",
    "node_id": 15,
    "usercode_code_11": ""
  },

  "UID": "zwave:device:71bc65a0:node15",
  "thingTypeUID": "zwave:yale_ykfcon_00_000"
}

So If I push this through a transform JSONPATH with just the $.configuration filter I would have expected somthing like this:

{
    "binding_cmdrepollperiod": 1500,
    "doorlock_timeout": 0,
    "usercode_label_6": "Kathy",
    "group_1": [
      "controller"
    ],
    "usercode_label_2": "Abi",
    "action_reinit": false,
    "usercode_code_20": "",
    "usercode_code_16": "",
    "usercode_code_17": "",
    "usercode_code_18": "",
    "usercode_code_19": "",
    "action_failed": false,
    "action_remove": false,
    "binding_pollperiod": 86400,
    "usercode_code_7": "",
    "action_heal": false,
    "usercode_code_8": "",
    "config_1_1": 1,
    "usercode_code_9": "",
    "config_2_1": 255,
    "usercode_label_1": "Milo",
    "usercode_code_3": "111111",
    "usercode_code_4": "",
    "usercode_code_5": "",
    "usercode_code_6": "111111",
    "config_7_1": 30,
    "usercode_code_12": "",
    "config_8_1": 0,
    "usercode_code_13": "",
    "usercode_code_1": "111111",
    "usercode_code_14": "",
    "usercode_code_2": "111111",
    "usercode_code_15": "",
    "config_3_1": 50,
    "config_4_1": 5,
    "config_5_1": 1,
    "usercode_code_10": "",
    "node_id": 15,
    "usercode_code_11": ""
  }

But instead I get this:

{ 
   binding_cmdrepollperiod=1500,
   doorlock_timeout=0,
   usercode_label_6=Kathy,
   group_1=[ 
      "controller"
   ],
   usercode_label_2=Abi,
   action_reinit=false,
   usercode_code_20=,
   usercode_code_16=,
   usercode_code_17=,
   usercode_code_18=,
   usercode_code_19=,
   action_failed=false,
   action_remove=false,
   binding_pollperiod=86400,
   usercode_code_7=,
   action_heal=false,
   usercode_code_8=,
   config_1_1=1,
   usercode_code_9=,
   config_2_1=255,
   usercode_label_1=Milo,
   usercode_code_3=111111,
   usercode_code_4=,
   usercode_code_5=,
   usercode_code_6=111111,
   config_7_1=30,
   usercode_code_12=,
   config_8_1=0,
   usercode_code_13=,
   usercode_code_1=111111,
   usercode_code_14=,
   usercode_code_2=111111,
   usercode_code_15=,
   config_3_1=50,
   config_4_1=5,
   config_5_1=1,
   usercode_code_10=,
   node_id=15,
   usercode_code_11=
}

I wanted to store this in JSON to call the values whenever I wanted but when I try and transform this I get this error:

17:07:29.837 [ERROR] [untime.internal.engine.RuleEngineImpl] - Rule 'LFD Test': An error occurred during the script execution: Could not invoke method: org.eclipse.smarthome.core.transform.actions.Transformation.transform(java.lang.String,java.lang.String,java.lang.String) on instance: null

Which is right.
So my question is, is there any method of extracting the configuration section as a JSON string from the main section without losing the quotation marks?

Maybe by using a Javascript transformation

That is not valid JSON then. The double quotes are required by the standard,

Yes I know it’s not valid JSON. It was valid when I started though!
When I run it through a transform to get the configuration section, it removes all the quotes!
The only thing I can think of is to use search functions in the string and trim the data around the section I actually want…

I suspect if you used Jython you could get it to work. I have used JSON in Python elsewhere. A Python dictionary is very closely related to JSON.

To repeat, JSONPATH is to extract values and is not really meant to extract subsets of correctly formatted JSON.

There will be ways to do it, if you must. Process the JSON in a javascript, or get JSONPATH to output an array that you can then code to repackage as JSON etc.

Why not just store the whole JSON source? It doesn’t cost you any more than storing a subset of it.

Why not extract the wanted values into a set of Items, all ready for when required later?

1 Like

I did think about that, and I think that will probably be the route I go down, I just didnt want to store the large amounts of other data (there is a bit more that what I posted above).

There are 20 values that could possibly be used which would mean 20 items.

To get the section I could use a regex transformation that I worked out:

(?<=configuration\": )((.|\n)*)(?=,\n  \"prop)

As you have said though I think I will just store the whole string.