JSON transform problem in OH 2.3

When I migratete to OH 2.3 problem wit JSON transform appeared:

forecastJson="{\"cod\":\"200\",\"message\":0.0025,\"cnt\":8,\"list\":[{\"dt\":1534572000,\"main\":{\"temp\":18.32,\"temp_min\":18.32,\"temp_max\":19.62,\"pressure\":1021.48,\"sea_level\":1031.67,\"grnd_level\":1021.48,\"humidity\":83,\"temp_kf\":-1.31},\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04d\"}],\"clouds\":{\"all\":68},\"wind\":{\"speed\":2.71,\"deg\":337.008},\"sys\":{\"pod\":\"d\"},\"dt_txt\":\"2018-08-18 06:00:00\"},{\"dt\":1534582800,\"main\":{\"temp\":22.64,\"temp_min\":22.64,\"temp_max\":23.51,\"pressure\":1022.21,\"sea_level\":1032.39,\"grnd_level\":1022.21,\"humidity\":74,\"temp_kf\":-0.87},\"weather\":[{\"id\":801,\"main\":\"Clouds\",\"description\":\"few clouds\",\"icon\":\"02d\"}],\"clouds\":{\"all\":24},\"wind\":{\"speed\":3.02,\"deg\":354.507},\"sys\":{\"pod\":\"d\"},\"dt_txt\":\"2018-08-18 09:00:00\"},{\"dt\":1534593600,\"main\":{\"temp\":24.32,\"temp_min\":24.32,\"temp_max\":24.76,\"pressure\":1022.01,\"sea_level\":1032.15,\"grnd_level\":1022.01,\"humidity\":74,\"temp_kf\":-0.44},\"weather\":[{\"id\":500,\"main\":\"Rain\",\"description\":\"light rain\",\"icon\":\"10d\"}],\"clouds\":{\"all\":20},\"wind\":{\"speed\":2.51,\"deg\":350.5},\"rain\":{\"3h\":0.495},\"sys\":{\"pod\":\"d\"},\"dt_txt\":\"2018-08-18 12:00:00\"},{\"dt\":1534604400,\"main\":{\"temp\":24.38,\"temp_min\":24.38,\"temp_max\":24.38,\"pressure\":1021.82,\"sea_level\":1032.09,\"grnd_level\":1021.82,\"humidity\":66,\"temp_kf\":0},\"weather\":[{\"id\":500,\"main\":\"Rain\",\"description\":\"light rain\",\"icon\":\"10d\"}],\"clouds\":{\"all\":0},\"wind\":{\"speed\":3.06,\"deg\":348.503},\"rain\":{\"3h\":2.1},\"sys\":{\"pod\":\"d\"},\"dt_txt\":\"2018-08-18 15:00:00\"},{\"dt\":1534615200,\"main\":{\"temp\":21.07,\"temp_min\":21.07,\"temp_max\":21.07,\"pressure\":1021.97,\"sea_level\":1032.35,\"grnd_level\":1021.97,\"humidity\":56,\"temp_kf\":0},\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"clear sky\",\"icon\":\"01d\"}],\"clouds\":{\"all\":0},\"wind\":{\"speed\":2.81,\"deg\":325.002},\"rain\":{},\"sys\":{\"pod\":\"d\"},\"dt_txt\":\"2018-08-18 18:00:00\"},{\"dt\":1534626000,\"main\":{\"temp\":15.67,\"temp_min\":15.67,\"temp_max\":15.67,\"pressure\":1023.38,\"sea_level\":1033.67,\"grnd_level\":1023.38,\"humidity\":68,\"temp_kf\":0},\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"clear sky\",\"icon\":\"01n\"}],\"clouds\":{\"all\":0},\"wind\":{\"speed\":2.56,\"deg\":333.501},\"rain\":{},\"sys\":{\"pod\":\"n\"},\"dt_txt\":\"2018-08-18 21:00:00\"},{\"dt\":1534636800,\"main\":{\"temp\":12.21,\"temp_min\":12.21,\"temp_max\":12.21,\"pressure\":1023.52,\"sea_level\":1033.85,\"grnd_level\":1023.52,\"humidity\":89,\"temp_kf\":0},\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"clear sky\",\"icon\":\"01n\"}],\"clouds\":{\"all\":0},\"wind\":{\"speed\":1.28,\"deg\":157.002},\"rain\":{},\"sys\":{\"pod\":\"n\"},\"dt_txt\":\"2018-08-19 00:00:00\"},{\"dt\":1534647600,\"main\":{\"temp\":11.15,\"temp_min\":11.15,\"temp_max\":11.15,\"pressure\":1023,\"sea_level\":1033.33,\"grnd_level\":1023,\"humidity\":87,\"temp_kf\":0},\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"clear sky\",\"icon\":\"01n\"}],\"clouds\":{\"all\":0},\"wind\":{\"speed\":1.72,\"deg\":177.001},\"rain\":{},\"sys\":{\"pod\":\"n\"},\"dt_txt\":\"2018-08-19 03:00:00\"}],\"city\":{\"id\":3092909,\"name\":\"Lublewo Gdanskie\",\"coord\":{\"lat\":54.2846,\"lon\":18.5039},\"country\":\"PL\"}}"
var String[] rainValues  = transform("JSONPATH","$.list[*].rain.3h", forecastJson).replace("[", "").replace("]", "").split(",") 

returned:
JsonPath expressions with more than one result are not allowed, please adapt your selector.

I found such thread:

but still I do not know how to change my code :frowning:

Well, you are trying to create a string list and thatā€™s not possible any more. You have to select a single value for JSON transformation.

I switched to the jq executable. If you are on linux this is easy. Instead of http binding and jsonpath transformation i now use exec binding with curl and jq.

jq - commandline JSON processor [version 1.5-1-a5b5cbe]
Usage: jq [options] <jq filter> [file...]

        jq is a tool for processing JSON inputs, applying the
        given filter to its JSON text inputs and producing the
        filter's results as JSON on standard output.
        The simplest filter is ., which is the identity filter,
        copying jq's input to its output unmodified (except for
        formatting).
        For more advanced filters see the jq(1) manpage ("man jq")
        and/or https://stedolan.github.io/jq
2 Likes

You could use a js transform to return a string with the values split by ,
and then use a string.split(",").get(*) to assign to the different items:

rainvalues.js

(function(datastring) {
var data = JSON.parse(datastring);
var listValues = data.list;
var text = "";
var i;
for (i = 0; i < listValues.length; i++) {
    if (listValues[i].hasOwnProperty('rain')) {
        if (listValues[i].rain['3h'] !== undefined) {
            text = text + listValues[i].rain['3h'].toString() + ",";
        }
    }
}
text = text.substring(0, text.length-1);
return text;
})(input)

In your rule:

var String rainValues  = transform("JS","$.list[*].rain.3h", rainvalues.js)
item1.postUpdate(rainValues.split(",").get(0))
item2.postUpdate(rainValues.split(",").get(1))
...

The only issue is that you donā€™t know how many rainValues you are going to get

1 Like

If youā€™d like to use jq, this filter will work return exactly what the JSONPATH didā€¦

[.list[].rain."3h" | numbers]
1 Like

When I try it Iā€™ve got:

2018-08-20 12:25:01.278 [ERROR] [ntime.internal.engine.ExecuteRuleJob] - Error during the execution of rule 'Wtr_algorithm': The name 'rainvalues' cannot be resolved to an item or type; line 400, column 65, length 10

In my code:

var String rainValuesStr  = transform("JS","$.list[*].rain.3h", rainvalues.js)
logInfo( "FILE", "Wtr_algorithm: rainValuesStr [" + rainValuesStr +  "]")

and Iā€™ve added js file to ā€˜transformā€™ directory.

Michal

My fault.
Put rain values.js in ā€œā€

When you use ā€œā€ it will be treated as a string that should be converted.

Michal

How do you execute jq from OH? Using Exec binding?

I got it the wrong way around:

var String rainValues = transform("JS", "rainvalues.js", forecastJson)

I use it with executeCommandLine. There is an example in the post you linked to in the OP, which also includes getting the data through curl. This may work for youā€¦

import java.util.List
...
val String forecastJson="{\"cod\":\"200\",\"message\":0.0025,\"cnt\":8,\"list\":[{\"dt\":1534572000,\"main\":{\"temp\":18.32,\"temp_min\":18.32,\"temp_max\":19.62,\"pressure\":1021.48,\"sea_level\":1031.67,\"grnd_level\":1021.48,\"humidity\":83,\"temp_kf\":-1.31},\"weather\":[{\"id\":803,\"main\":\"Clouds\",\"description\":\"broken clouds\",\"icon\":\"04d\"}],\"clouds\":{\"all\":68},\"wind\":{\"speed\":2.71,\"deg\":337.008},\"sys\":{\"pod\":\"d\"},\"dt_txt\":\"2018-08-18 06:00:00\"},{\"dt\":1534582800,\"main\":{\"temp\":22.64,\"temp_min\":22.64,\"temp_max\":23.51,\"pressure\":1022.21,\"sea_level\":1032.39,\"grnd_level\":1022.21,\"humidity\":74,\"temp_kf\":-0.87},\"weather\":[{\"id\":801,\"main\":\"Clouds\",\"description\":\"few clouds\",\"icon\":\"02d\"}],\"clouds\":{\"all\":24},\"wind\":{\"speed\":3.02,\"deg\":354.507},\"sys\":{\"pod\":\"d\"},\"dt_txt\":\"2018-08-18 09:00:00\"},{\"dt\":1534593600,\"main\":{\"temp\":24.32,\"temp_min\":24.32,\"temp_max\":24.76,\"pressure\":1022.01,\"sea_level\":1032.15,\"grnd_level\":1022.01,\"humidity\":74,\"temp_kf\":-0.44},\"weather\":[{\"id\":500,\"main\":\"Rain\",\"description\":\"light rain\",\"icon\":\"10d\"}],\"clouds\":{\"all\":20},\"wind\":{\"speed\":2.51,\"deg\":350.5},\"rain\":{\"3h\":0.495},\"sys\":{\"pod\":\"d\"},\"dt_txt\":\"2018-08-18 12:00:00\"},{\"dt\":1534604400,\"main\":{\"temp\":24.38,\"temp_min\":24.38,\"temp_max\":24.38,\"pressure\":1021.82,\"sea_level\":1032.09,\"grnd_level\":1021.82,\"humidity\":66,\"temp_kf\":0},\"weather\":[{\"id\":500,\"main\":\"Rain\",\"description\":\"light rain\",\"icon\":\"10d\"}],\"clouds\":{\"all\":0},\"wind\":{\"speed\":3.06,\"deg\":348.503},\"rain\":{\"3h\":2.1},\"sys\":{\"pod\":\"d\"},\"dt_txt\":\"2018-08-18 15:00:00\"},{\"dt\":1534615200,\"main\":{\"temp\":21.07,\"temp_min\":21.07,\"temp_max\":21.07,\"pressure\":1021.97,\"sea_level\":1032.35,\"grnd_level\":1021.97,\"humidity\":56,\"temp_kf\":0},\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"clear sky\",\"icon\":\"01d\"}],\"clouds\":{\"all\":0},\"wind\":{\"speed\":2.81,\"deg\":325.002},\"rain\":{},\"sys\":{\"pod\":\"d\"},\"dt_txt\":\"2018-08-18 18:00:00\"},{\"dt\":1534626000,\"main\":{\"temp\":15.67,\"temp_min\":15.67,\"temp_max\":15.67,\"pressure\":1023.38,\"sea_level\":1033.67,\"grnd_level\":1023.38,\"humidity\":68,\"temp_kf\":0},\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"clear sky\",\"icon\":\"01n\"}],\"clouds\":{\"all\":0},\"wind\":{\"speed\":2.56,\"deg\":333.501},\"rain\":{},\"sys\":{\"pod\":\"n\"},\"dt_txt\":\"2018-08-18 21:00:00\"},{\"dt\":1534636800,\"main\":{\"temp\":12.21,\"temp_min\":12.21,\"temp_max\":12.21,\"pressure\":1023.52,\"sea_level\":1033.85,\"grnd_level\":1023.52,\"humidity\":89,\"temp_kf\":0},\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"clear sky\",\"icon\":\"01n\"}],\"clouds\":{\"all\":0},\"wind\":{\"speed\":1.28,\"deg\":157.002},\"rain\":{},\"sys\":{\"pod\":\"n\"},\"dt_txt\":\"2018-08-19 00:00:00\"},{\"dt\":1534647600,\"main\":{\"temp\":11.15,\"temp_min\":11.15,\"temp_max\":11.15,\"pressure\":1023,\"sea_level\":1033.33,\"grnd_level\":1023,\"humidity\":87,\"temp_kf\":0},\"weather\":[{\"id\":800,\"main\":\"Clear\",\"description\":\"clear sky\",\"icon\":\"01n\"}],\"clouds\":{\"all\":0},\"wind\":{\"speed\":1.72,\"deg\":177.001},\"rain\":{},\"sys\":{\"pod\":\"n\"},\"dt_txt\":\"2018-08-19 03:00:00\"}],\"city\":{\"id\":3092909,\"name\":\"Lublewo Gdanskie\",\"coord\":{\"lat\":54.2846,\"lon\":18.5039},\"country\":\"PL\"}}".replace("\"","\\\"")
val List<String> rainValues = executeCommandLine("/bin/sh@@-c@@/usr/bin/echo \"" + forecastJson + "\" | /usr/bin/jq '.list[].rain.\"3h\" | numbers'",1000).split("\n")
logDebug("Rules","Test: rainValues=[{}]",rainValues.toString)

This logsā€¦

Test: rainValues=[[0.495, 2.1]]
1 Like

Ok it works :slight_smile:

			var String[] rainValues  = transform("JS","rainvalues.js",forecastJson).replace("[", "").replace("]", "").split(",") 

  			rainfallMm = 0

			if(rainValues.get(0)!="NULL")		
				for (var i = 0; i < rainValues.length; i++) {						
					rainfallMm = rainfallMm  + (Double::parseDouble(rainValues.get(i)))
				}

Yeahhhh!!!