Skip to content
Plugins (183)

json

stable

Parse, serialize, query, merge, diff, validate, flatten, and unflatten JSON data.

use plugin json::{parse, stringify, stringify_pretty, …}
12 functions Data Formats
Runs with the native Zolo host

Plugin snippets can be edited in the Playground, but native capabilities are executed locally with the Zolo CLI.

/ filter jk navigate Esc clear
Functions (12)
  1. parse Parse a JSON string into a value
  2. stringify Serialize a value to a JSON string
  3. stringify_pretty Serialize with indentation
  4. parse_file Parse JSON from a file path
  5. write_file Write a value as pretty JSON to a file
  6. get_path Read a nested value by dot-path
  7. set_path Write a nested value by dot-path
  8. merge Deep-merge two tables
  9. diff Compute added/removed/changed between two values
  10. validate_schema Validate data against a simple schema
  11. flatten Flatten nested tables to dot-keyed pairs
  12. unflatten Restore dot-keyed pairs to nested tables

From import to result

  1. 01Import only what you use
  2. 02Copy the smallest example
  3. 03Run it with the Zolo CLI

Overview

json bridges JSON text and ordinary Zolo values. Parsing turns JSON into plain tables — objects become string-keyed tables and arrays become 1-indexed integer-keyed tables — so there is no opaque document type to learn: a parsed document is just a table you index, iterate, and pass around. Serialization runs the same mapping in reverse, treating a table whose keys are all integers as a JSON array and any other table as an object.

Beyond parse/stringify, the plugin adds a small toolkit for working with that data: dot-path read/write (get_path, set_path), deep merge and diff, lightweight schema validation, and flatten/unflatten for collapsing nested structures into single-level dot-keyed tables. The path-based and transform helpers never mutate their input — they return new tables — so they compose cleanly. Reach for json whenever you load configuration, exchange data with an HTTP API, or need to compare or reshape structured values.

Common patterns

Load a config file, apply runtime overrides, and read a nested value back out:

use plugin json::{parse_file, merge, get_path}

let base = parse_file("config.json")
let config = merge(base, #{"server": #{"port": 8080}})
print("port: {get_path(config, "server.port")}")

Validate an incoming payload against a schema before using it:

use plugin json::{parse, validate_schema}

let schema = #{
  "type": "object",
  "required": ["name", "age"],
  "properties": #{
    "name": #{"type": "string"},
    "age":  #{"type": "number"}
  }
}
let data = parse('{"name": "Alice", "age": 30}')
let report = validate_schema(data, schema)
if report["valid"] {
  print("ok: {get_path(data, "name")}")
} else {
  print("first error: {report["errors"][1]}")
}

Compare two documents and persist the merged result:

use plugin json::{parse, diff, merge, write_file}

let current = parse('{"theme": "light", "font": 12}')
let incoming = parse('{"theme": "dark", "font": 12}')
let changes = diff(current, incoming)
print("{changes[1]["path"]} {changes[1]["type"]}")
write_file("settings.json", merge(current, incoming))

Parse a JSON string into a value

Parses a JSON string and returns the equivalent Zolo value. Objects become string-keyed tables; arrays become 1-indexed integer-keyed tables.

use plugin json::{parse}

let data = parse('{"name": "Alice", "scores": [10, 20, 30]}')
print(data["name"])
print(data["scores"][1])

Because the result is an ordinary table, parsed values flow straight into the other helpers:

use plugin json::{parse, get_path}

let payload = parse('{"user": {"roles": ["admin", "editor"]}}')
print(get_path(payload, "user.roles.0"))

Serialize a value to a JSON string

Serializes a Zolo value to a compact JSON string. Integer-keyed tables become JSON arrays; string-keyed tables become JSON objects.

use plugin json::{stringify}

let text = stringify(#{"x": 1, "y": 2, "tags": ["a", "b"]})
print(text)

A table whose keys are all integers serializes as a JSON array, so lists round-trip without extra wrapping:

use plugin json::{stringify}

print(stringify([1, 2, 3]))

Serialize with indentation

Serializes a value to a human-readable JSON string. indent defaults to 2 spaces.

use plugin json::{stringify_pretty}

let obj = #{"name": "Bob", "active": true}
print(stringify_pretty(obj))
print(stringify_pretty(obj, 4))

Parse JSON from a file path

Reads a file from disk and parses its contents as JSON.

use plugin json::{parse_file}

let config = parse_file("config.json")
print(config["host"])
print(config["port"])

Write a value as pretty JSON to a file

Serializes value as pretty-printed JSON and writes it to the file at path, overwriting any existing content.

use plugin json::{write_file}

let settings = #{"theme": "dark", "font_size": 14}
write_file("settings.json", settings)

Read a nested value by dot-path

Reads a nested value using a dot-separated path string. Array indices are 0-based in the path (e.g. "users.0.name").

use plugin json::{parse, get_path}

let data = parse('{"users": [{"name": "Alice"}, {"name": "Bob"}]}')
let name = get_path(data, "users.0.name")
print(name)

Write a nested value by dot-path

Returns a new table with the value at the dot-path set to value. Creates intermediate tables as needed. The original table is not mutated.

use plugin json::{parse, set_path, stringify}

let data = parse('{"user": {"name": "Alice"}}')
let updated = set_path(data, "user.name", "Bob")
print(stringify(updated))

Paths that do not exist yet are created on the way down, so set_path doubles as a builder for deep structures:

use plugin json::{set_path, stringify}

let cfg = set_path(#{}, "server.tls.enabled", true)
print(stringify(cfg))

Deep-merge two tables

Deep-merges table2 into table1. Keys in table2 overwrite matching keys in table1; nested tables are merged recursively.

use plugin json::{merge, stringify}

let base = #{"host": "localhost", "port": 3000, "debug": false}
let overrides = #{"port": 8080, "debug": true}
let config = merge(base, overrides)
print(stringify(config))

Compute added/removed/changed between two values

Returns a list of changes between two values. Each entry is a table with path, type ("added", "removed", or "changed"), and old/new values where applicable.

use plugin json::{parse, diff}

let v1 = parse('{"a": 1, "b": 2}')
let v2 = parse('{"a": 1, "b": 3, "c": 4}')
let changes = diff(v1, v2)
print(changes[1]["path"])
print(changes[1]["type"])

Validate data against a simple schema

Validates data against a simple schema table and returns {valid, errors}. The schema supports type ("object", "array", "string", "number", "boolean"), required (list of field names), and properties (nested schemas).

use plugin json::{parse, validate_schema}

let schema = #{
  "type": "object",
  "required": ["name", "age"],
  "properties": #{
    "name": #{"type": "string"},
    "age":  #{"type": "number"}
  }
}
let data = parse('{"name": "Alice", "age": 30}')
let result = validate_schema(data, schema)
print(result["valid"])

Flatten nested tables to dot-keyed pairs

Flattens a nested table into a single-level table whose keys are dot-separated paths. The default separator is ".".

use plugin json::{parse, flatten}

let data = parse('{"a": {"b": 1, "c": {"d": 2}}}')
let flat = flatten(data)
print(flat["a.b"])
print(flat["a.c.d"])

Array elements flatten with 0-based index segments, and a custom separator is supported:

use plugin json::{parse, flatten}

let data = parse('{"tags": ["x", "y"]}')
let flat = flatten(data, "/")
print(flat["tags/0"])
print(flat["tags/1"])

Restore dot-keyed pairs to nested tables

Reconstructs a nested table from a flat dot-keyed table. Inverse of flatten.

use plugin json::{unflatten, stringify}

let flat = #{"a.b": 1, "a.c.d": 2}
let nested = unflatten(flat)
print(stringify(nested))

Global index

Find your way through Zolo

Try an idea

Start here

9 results

9 results

en