> ## Documentation Index
> Fetch the complete documentation index at: https://docs.coreflux.org/llms.txt
> Use this file to discover all available pages before exploring further.

# Working with JSON

> Read JSON fields with GET JSON in Actions, handle nested payloads and missing keys, and publish structured output through Models.

## Overview

Most MQTT payloads in IoT systems are JSON — from devices, HTTP webhooks, industrial gateways, and partner APIs. In Actions you **read** fields with `GET JSON` and **write** structured output with [`PUBLISH MODEL`](/v2.0/lot-language/models/publish-model). Use raw `PAYLOAD AS DOUBLE` only when the message is a single value with no structure.

For when to choose scalar topics, JSON ingress, or Models at the architecture level, see [Choosing data formats](/v2.0/lot-language/usage-patterns/data-layer#choosing-data-formats) on the data layer page.

<Tip>
  **Like fishing one specific item out of a packed grocery bag.** You don't unpack the whole bag — you reach in, grab the field by name, and leave the rest where it is.
</Tip>

For the full `GET JSON` syntax table and edge cases in the operations reference, see [Operations — GET JSON](/v2.0/lot-language/actions/operations#get-json).

***

## When to Use This

Any time an incoming MQTT message is a JSON object. Typical sources:

* Sensors and PLCs publishing JSON over MQTT
* REST or webhook Routes that forward JSON bodies to topics
* Cloud or SCADA integrations bridged into the broker

***

## Reading JSON Fields

[`GET JSON`](/v2.0/lot-language/actions/operations#get-json) takes a field name (or a dotted path), the source (almost always `PAYLOAD`), and a target type. It works inside any expression that needs a value:

```lot wrap theme={"theme":"css-variables","languages":{"custom":["/languages/lot.json"]}}
DEFINE ACTION ProcessReading
ON TOPIC "sensors/reading" DO
    SET "device_id" WITH (GET JSON "id" IN PAYLOAD AS STRING)
    SET "temperature" WITH (GET JSON "temperature" IN PAYLOAD AS DOUBLE)
    SET "active" WITH (GET JSON "enabled" IN PAYLOAD AS BOOL)

    PUBLISH TOPIC "processed/" + {device_id} + "/temperature" WITH {temperature}
```

Supported target types are `STRING`, `DOUBLE`, `INT`, and `BOOL`. The conversion happens at extraction time, so by the time the value is in your variable it is already typed correctly for comparisons and math.

***

## Nested Paths

For nested objects, use dot notation. For arrays, use bracket notation. Mix them freely:

```lot wrap theme={"theme":"css-variables","languages":{"custom":["/languages/lot.json"]}}
DEFINE ACTION ProcessNested
ON TOPIC "sensors/payload" DO
    SET "temp" WITH (GET JSON "data.sensors.temperature" IN PAYLOAD AS DOUBLE)
    SET "first_reading" WITH (GET JSON "readings[0].value" IN PAYLOAD AS DOUBLE)
    SET "second_id" WITH (GET JSON "readings[1].sensor_id" IN PAYLOAD AS STRING)
```

For a payload like:

```json wrap theme={"theme":"css-variables","languages":{"custom":["/languages/lot.json"]}}
{
  "data": { "sensors": { "temperature": 23.5 } },
  "readings": [
    { "sensor_id": "S1", "value": 100 },
    { "sensor_id": "S2", "value": 200 }
  ]
}
```

`{temp}` becomes `23.5`, `{first_reading}` becomes `100`, `{second_id}` becomes `"S2"`.

***

## Handling Missing Fields

If a field is absent, `GET JSON` returns a type-appropriate default: empty string for `STRING`, `0` for numeric types, `FALSE` for `BOOL`. For optional fields, check explicitly with `EMPTY`:

```lot wrap theme={"theme":"css-variables","languages":{"custom":["/languages/lot.json"]}}
SET "battery" WITH (GET JSON "battery_level" IN PAYLOAD AS DOUBLE)
IF {battery} == EMPTY THEN
    PUBLISH TOPIC "alerts/missing_field" WITH "battery_level not reported"
ELSE
    PUBLISH TOPIC "processed/battery" WITH {battery}
```

This pattern matters when you consume data from third parties — webhooks and partner APIs often omit fields rather than send nulls.

***

## End-to-End: Extract JSON and Publish a Model

To publish structured JSON without hand-building strings, define a **COLLAPSED** Model with typed fields and use `PUBLISH MODEL ... TO ... WITH` from an Action. The broker assembles the JSON for you.

```lot wrap theme={"theme":"css-variables","languages":{"custom":["/languages/lot.json"]}}
DEFINE MODEL SensorDataRecord COLLAPSED
    ADD STRING "sensor_id"
    ADD STRING "sensor_type"
    ADD DOUBLE "temperature"
    ADD DOUBLE "pressure"
    ADD STRING "timestamp"
    ADD STRING "quality_status"

DEFINE ACTION ProcessSensorJSON
ON TOPIC "sensors/+/json_data" DO
    SET "sensor_id" WITH TOPIC POSITION 2

    SET "temperature_val" WITH (GET JSON "temperature" IN PAYLOAD AS DOUBLE)
    SET "pressure_val" WITH (GET JSON "pressure" IN PAYLOAD AS DOUBLE)
    SET "sensor_type" WITH (GET JSON "type" IN PAYLOAD AS STRING)
    SET "quality" WITH (GET JSON "quality_status" IN PAYLOAD AS STRING)

    PUBLISH MODEL SensorDataRecord TO "sensors/processed/" + {sensor_id} WITH
        sensor_id = {sensor_id}
        sensor_type = {sensor_type}
        temperature = {temperature_val}
        pressure = {pressure_val}
        timestamp = TIMESTAMP "UTC"
        quality_status = {quality}
```

| Step | What Happens                                                                       |
| ---- | ---------------------------------------------------------------------------------- |
| 1    | Action triggers when any sensor publishes JSON to `sensors/+/json_data`            |
| 2    | `GET JSON` extracts each field with the correct type                               |
| 3    | `PUBLISH MODEL` builds a clean JSON object and publishes it to the processed topic |

See [Publish Model](/v2.0/lot-language/models/publish-model) for more on COLLAPSED models and field mapping.

***

## Next Steps

<CardGroup cols={2}>
  <Card title="Designing your data layer" icon="sitemap" href="/v2.0/lot-language/usage-patterns/data-layer">
    Topic trees, scalar vs JSON payloads, and when to use Models.
  </Card>

  <Card title="Operations — GET JSON" icon="gear" href="/v2.0/lot-language/actions/operations#get-json">
    Full syntax reference for GET JSON and related operations.
  </Card>
</CardGroup>
