---
slug: 36-json
title: JSON
description: Serialize and parse JSON in Synsema with json_encode / json_decode — round-trippable, with safe handling of secrets, bytes and decimal.
example_ids: [json]
---

# JSON

Two builtins, fully round-trippable: `json_decode(json_encode(x))` reconstructs `x`.

```synsema
-- Doc example: JSON encode/decode (pure, round-trippable).
intent: "doc example: JSON"

print(json_encode({"name": "Ada", "tags": ["x", "y"], "n": 3}))    -- run shows the JSON

test "encode then decode reconstructs the value"
    let data be {"name": "Ada", "tags": ["x", "y"], "n": 3}
    let s be json_encode(data)
    let back be json_decode(s)
    assert_eq(back["name"], "Ada")
    assert_eq(back["n"], 3)
    assert_eq(length(back["tags"]), 2)
```

## Encode & decode

```synsema
json_encode(value)      -- value → JSON text
json_for_script(value)  -- same JSON, `<` `>` `&` escaped \u00XX — SAFE inside an inline <script>
json_decode(text)       -- JSON text → value (object→map, array→list, …)
```

## What encode does with special values

- `secret` → `"[redacted]"` (safe — never leaks the plaintext).
- `bytes` → a base64 string.
- `decimal` (`1.50d`) → an exact JSON number.
- `nothing` → `null`.

This is the idiomatic way to store structured data in a text/Redis value:

```synsema
redis_set("cfg", json_encode({"theme": "dark", "n": 3}))
let cfg be json_decode(redis_get("cfg"))
```

`json_decode` errors clearly on invalid JSON. Note that responses from the HTTP client already expose a parsed `json of r` (see **[HTTP client](/en/0.6.x/32-http-client)**).
