Javascript transformation for JSON

Hi !

I have a basic question how to parse json which I get from the HTTP Binding.
My JSON looks like the following:
{
“getusertransactions”:{
“version”:“1.0.0”,
“runtime”:11.106967926025,
“data”:{
“transactions”:[
{
“id”:6975736,
“username”:“arnoldmaderthaner”,
“type”:“Fee”,
“amount”:0.0211522,
“coin_address”:null,
“timestamp”:“2018-01-10 13:19:27”,
“txid”:null,
“height”:1789426,
“blockhash”:“af0c85ad9ec7753a426128d3e77384d2bc60925d420fc07cf0885cd8e8a12e32”,
“confirmations”:25
},
{
“id”:6975717,
“username”:“arnoldmaderthaner”,
“type”:“Credit”,
“amount”:2.11522006,
“coin_address”:null,
“timestamp”:“2018-01-10 13:19:27”,
“txid”:null,
“height”:1789426,
“blockhash”:“af0c85ad9ec7753a426128d3e77384d2bc60925d420fc07cf0885cd8e8a12e32”,
“confirmations”:25
},
{
“id”:6970074,
“username”:“arnoldmaderthaner”,
“type”:“Fee”,
“amount”:0.02569984,
“coin_address”:null,
“timestamp”:“2018-01-10 13:16:29”,
“txid”:null,
“height”:1789422,
“blockhash”:“d1225b61a20a14ca352644e775db83beb5f66549f29394a3cb2e387260daaf05”,
“confirmations”:29
}
],
“transactionsummary”:{
“Credit”:3797.41269803,
“Debit_AP”:3517.01453348,
“Fee”:37.97412718,
“TXFee”:0.07
}
}
}
}

Now I want to write some javascript to get the average amount of all the transactions that have a type equal to “Credit”.
Here is my javascript:

(function(i) {
var data = JSON.parse(i).getusertransactions.data.transactions;
var sum = 0, n = 0;
for (j in data) {
if(j.type == “Credit”)
{
sum += j.amount;
n++;
}
}
console.log(sum/n);
return sum/n;
})(input)

anyone knows what could be wrong with the JS ?

Hi,
There is something wrong with the quotes in the JSON you´ve posted. It seems like the quotes has been replaced by tho single quotes… Never mind. I´ve re-posted it with the correct quotes below

{
	"getusertransactions": {
		"version": "1.0.0",
		"runtime": 11.106967926025,
		"data": {
			"transactions": [{
					"id": 6975736,
					"username": "arnoldmaderthaner",
					"type": "Fee",
					"amount": 0.0211522,
					"coin_address": null,
					"timestamp": "2018-01-10 13:19:27",
					"txid": null,
					"height": 1789426,
					"blockhash": "af0c85ad9ec7753a426128d3e77384d2bc60925d420fc07cf0885cd8e8a12e32",
					"confirmations": 25
				},
				{
					"id": 6975717,
					"username": "arnoldmaderthaner",
					"type": "Credit",
					"amount": 2.11522006,
					"coin_address": null,
					"timestamp": "2018-01-10 13:19:27",
					"txid": null,
					"height": 1789426,
					"blockhash": "af0c85ad9ec7753a426128d3e77384d2bc60925d420fc07cf0885cd8e8a12e32",
					"confirmations": 25
				},
				{
					"id": 6970074,
					"username": "arnoldmaderthaner",
					"type": "Fee",
					"amount": 0.02569984,
					"coin_address": null,
					"timestamp": "2018-01-10 13:16:29",
					"txid": null,
					"height": 1789422,
					"blockhash": "d1225b61a20a14ca352644e775db83beb5f66549f29394a3cb2e387260daaf05",
					"confirmations": 29
				}
			],
			"transactionsummary": {
				"Credit": 3797.41269803,
				"Debit_AP": 3517.01453348,
				"Fee": 37.97412718,
				"TXFee": 0.07
			}
		}
	}
}

javascript is not my forte, but you can use a JSON PATH expression to extract the amount where type is credit

$.getusertransactions.data.transactions.[?(@.type == 'Credit')].amount

You will get an array as result and then you could run through that array for example in a rule (in OpenHAB) to figure out the average.

Hi !

thanks for your reply.
Where do you store than the array in openhab so that I can process it in a
rule ? Can I also do this inside the JS transformation so that I only get 1
Number item that has the average value stored ?

You could do

var myResult = transform("JSONPATH","$.getusertransactions.data.transactions.[?(@.type == 'Credit')].amount",yourJSON)

For more information you should have a look at https://docs.openhab.org/addons/transformations.html

If you JSON is on a URL you can do

val String yourJSON = sendHttpGetRequest("http://www.xxxxxxx.json")

thats clear but than I get again a string but I would need to loop through the amounts array returned from the jsonpath to do calculations. how can I do that ?

Hi again,

This is an interesting problem so I had a look and came up with a solution. It is NOT PRETTY and I would think that someone in this forum could come up with a more elegant solution. You should be able to put the following code in a rule and play with it.

//the json String
val String jsonString = sendHttpGetRequest("http://www.xxxxxxx.json")

//the jsonpath expression
var String jsonPath = "$.getusertransactions.data.transactions.[?(@.type == 'Credit')].amount" 

// get the results from the JSONPATH transformation
var jsonResult = transform("JSONPATH",jsonPath,jsonString)

// get the number of returned elements from the JSONPATH
var jsonNumResults = transform("JSONPATH","$.length()",jsonResult)

var Number sum = 0
var Number average = 0
var Number numres = Integer.parseInt(jsonNumResults)
var Number i = 0

while (i < numres) {
         // This is basically a transformation using jsonpath where the path expression is "$[i]" and then converted to float from string and added to sum
         sum = sum + Float.parseFloat(transform("JSONPATH",String::format("$[%s]",i.toString()),jsonResult))
         average = sum / numres
         i = i + 1
 }
logInfo("The sum is  :",sum.toString())
logInfo("The average is :",average.toString())