Skip to main content
The hosted extractor mapping language translates JSON structures to other JSON structures. The language is similar to JavaScript and is purely functional. A mapping is a single expression that describes how to build one JSON structure from another.

Variables

Use these input objects to define a mapping:
  • input - This is the content of the received message, parsed into an object.
  • context - This contains information about the message. The content of this object varies between the different hosted extractors. For MQTT, the context object contains
    • topic: which topic the message arrived at
For examples of using these variables, see Handling more data in a single message. When variables are objects or arrays they can be selected from. For example, given the object
{
  "someField": 123,
  "someArray": [1, 2, 3, { "nested": [1, 2, 3] }]
}
you can select from an object with
input.someField -> 123
or
input["someField"] -> 123
You select from arrays with
input.someArray[0] -> 1
and from the end of arrays with
input.someArray[-2] -> 3
Selectors can be nested as
input.someArray[3].nested[2] -> 3
Selectors can contain expressions
input.someArray[1 + 1] -> 3

Functions

The hosted extractor mapping language contains a set of predefined functions, which can be used to transform the input in other ways. For example,
float("1.4") -> 1.4
will try to transform the input from a string to a number, which may fail. Any function can also be called postfix, as a method on a value, so you could instead write
"1.4".float() -> 1.4
This is especially useful when dealing with chained operations. See also Functions.

Lambda expressions

Some functions can take user defined functions as arguments, such as map, reduce, or filter. To create the functions for these, use Lambda notation: argument => return. If the function takes no arguments, use () as the input to the function. If a function takes multiple values, denote them as a tuple: (arg1, arg2).

Examples

If we want to turn the list [1, 2, 3, 4] into [2, 4, 6, 8] we can use map to apply a function to each member of the list, and write a lambda function that doubles each value:
[1, 2, 3, 4].map(number => number * 2) -> [2, 4, 6, 8]
If you want to remove all nulls from a list, use the filter function, and write a lambda function that returns true if the value is the null type using the is operator:
[0, 1, 2, 3, 4, null, 5].filter(item => !(item is "null")) -> [0, 1, 2, 3, 4, 5]
To sum all the numbers from 1 through 10, use the reduce function to iteratively add the next member of the list to an aggregate:
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10].reduce((sum, next) => sum + next, 0) -> 110

Operators

The operators take one or two inputs and output some value. The operators are:

Plus

1 + 2 + 3 -> 6 Adds two numbers together.

Minus

1 - 2 - 3 -> -4 Subtracts a number from another.

Multiply

2 * 3 -> 6 Multiplies two numbers.

Divide

3 / 2 -> 1.5 Divides one number by another.

And

true && false -> false Boolean AND, returns true if the inputs are both not null or false.

Or

true || false -> true Boolean OR, returns true if either input is not null or false.

Equals

1 == 2 -> false Checks for exact equality. The inputs must be the same type, or this will be false.

Not equals

1 != 2 -> true Checks for inequality.

Greater than

2 > 3 -> false Checks if the first number is greater than the second number.

Greater than or equal

2 >= 3 -> false Checks if the first number is greater than or equal to the second number.

Less than

2 < 3 -> true Checks if the first number is less than the second number.

Less than

2 <= 3 -> true Checks if the first number is less than or equal to the second number.

Modulo

5 % 2 -> 1 Computes the modulus, or remainder, of the first argument divided by the second argument.

Is

5 is float This is the type check operator, used to check if the first argument is the type given by the second argument. The valid types are
  • null
  • object
  • array
  • string
  • number
  • float
  • int
  • bool
Any float or int is also number.

If expressions

You can use functional-style if expressions. For example
if 2 > 3 {
  "hello"
} else if 2 == 2 {
  "world"
} else {
  "goodbye"
}
will return "world". There is an if function as well, but using expressions usually results in cleaner code.

Objects

You can create JSON objects with familiar JSON syntax:
{
  "hello": 123,
  "test": input.something
}
These objects can be accessed, just like input variables: { "hello": 123 }.hello You can concat objects using the ... operator:
{
  "test": 123,
  ...{
    "hello": "world"
  },
  ...{
    "world": "hello"
  }
}
will yield the object
{
  "test": 123,
  "hello": "world",
  "world": "hello"
}
Object keys can also be expressions: { concat("he", "llo"): "world" } will yield an object { "hello": "world" }

Arrays

Arrays can be created using a JSON syntax: [1, 2, 3] You can access arrays using brackets, just like with inputs: [1, 2, 3][0] -> 1 Arrays also support the ... operator:
[
  1,
  ...[2, 3],
  ...[4, 5]
]
will yield [1, 2, 3, 4, 5]

Macros

Define your own reusable macros at the top of your mapping file:
#my_macro := (a, b) => a + b;

// Then use it later in the mapping expression
my_macro(3, 4) -> 7
Macros may call each other, but may not form loops.
#my_macro := (a, b) => my_macro(1, 2); // Illegal

#my_macro_1 := a => a + 1;
#my_macro_2 := b => my_macro_1(b) + 1; // Legal
Avoid using the same argument name in macros that call each other. In the example above, it wouldn’t be allowed to have my_macro_1 take an argument named b.
Last modified on December 9, 2025