Trying to extract GPS coordinates from JSON

You can use REGEX transform to achieve what you want. I just didn’t test your expression, but now I have. This will work:

JSONPATH:$.['lat', 'lon', 'alt']∩REGEX:s/.*lat=(-?\d+), lon=(-?\d+), alt=(-?\d+).*/$1,$2,$3/

Note, the above works if you created the Thing in UI and pasted that in the channel config. But if you’re creating your things using .things file, double the backslash like this:

JSONPATH:$.['lat', 'lon', 'alt']∩REGEX:s/.*lat=(-?\\d+), lon=(-?\\d+), alt=(-?\\d+).*/$1,$2,$3/

Example of a .things file:

Thing mqtt:topic:mosquitto:test3 (mqtt:broker:mosquitto) {
  Channels:
    Type string: test [stateTopic="test/test", transformationPattern="JSONPATH:$.['lat', 'lon', 'alt']∩REGEX:s/.*lat=(-?\\d+), lon=(-?\\d+), alt=(-?\\d+).*/$1,$2,$3/"]
}

Actually, you can even just use REGEX and skip the JSONPATH completely, if you’re sure the json string will be consistent. You just have to account for the newlines (add \s* or something)

Thing mqtt:topic:mosquitto:test3 (mqtt:broker:mosquitto) {
  Channels:
    Type string: test [stateTopic="test/test", transformationPattern="REGEX:s/.*\"lat\": (-?\\d+), \"lon\": (-?\\d+), \"alt\": (-?\\d+).*/$1,$2,$3/"]
}

Alternatively you can also do this using JS Scripting as above, or in JRuby

RB:|require 'json'; JSON.parse(input).slice('lat', 'lon', 'alt').values.join(',')

Explanation:

require "json"     # in Ruby you need to do this to use JSON.parse
JSON.parse(input)  # converts the json string into a Hash
    .slice("lat", "lon", "alt") # returns a hash with only those keys { lat=xxxx, lon=xxxx, alt=xxxx }
    .values        # returns only the values as an array: [xxx,xxxx,xxxx]
    .join(",")     # Returns a string by joining the elements of the array with a comma: "xxxx,xxxx,xxx"

Using JS / JRuby to parse the JSON instead of using regex is more robust and able to handle cases where the json field order is not as expected, or some fields are missing. But It is probably not likely to happen in your situation.

2 Likes