A general-purpose programming language written in JSON/JSONC, embeddable in Go applications.
Write programs in JSON. Run them anywhere Go runs.
{
"name": "hello",
"go_json": "1",
"steps": [
{"let": "name", "expr": "input.name ?? 'World'"},
{"return": "'Hello, ' + name + '!'"}
]
}$ go-json run hello.json --input '{"name": "Alice"}'
"Hello, Alice!"go-json fills a gap no existing tool covers: a general-purpose JSON programming language that is embeddable in Go applications.
| Tool | What It Does | What It Can't Do |
|---|---|---|
| jsonnet | Data templating | No side effects, no I/O, no control flow |
| jq | JSON transformation | Single-purpose, no general programming |
| AWS Step Functions | Cloud workflows | AWS-locked, no local execution |
| Node-RED | IoT/integration | Node.js-dependent, visual-only |
| CEL / expr-lang | Expression evaluation | Expressions only, no statements or functions |
go-json is a complete programming language — variables, functions, loops, structs, imports, error handling, parallel execution, I/O, and a built-in web server — all expressed as valid JSON.
- No-code/low-code engine — Build visual programming UIs where the output is JSON
- Business rules & automation — Define rules that non-developers can read and modify
- Embeddable scripting — Add user-programmable logic to your Go application
- Workflow orchestration — Multi-step processes with branching, loops, and parallel execution
- API servers — Declarative HTTP routing with middleware, auth, and templates
- Code generation — Write once in JSON, generate Go, JavaScript, or Python
go install github.com/bitcode-framework/go-json/cmd/go-json@latestgo get github.com/bitcode-framework/go-json@latestRequirements: Go 1.24+
Create hello.json:
{
"name": "hello",
"go_json": "1",
"steps": [
{"let": "greeting", "value": "Hello, World!"},
{"return": "greeting"}
]
}go-json run hello.jsonCreate greet.json:
{
"name": "greet",
"input": {"name": "string", "age": "int"},
"steps": [
{"let": "msg", "expr": "'Hello, ' + input.name + '! You are ' + string(input.age) + ' years old.'"},
{"return": "msg"}
]
}go-json run greet.json --input '{"name": "Alice", "age": 30}'{
"name": "math_demo",
"functions": {
"factorial": {
"params": {"n": "int"},
"returns": "int",
"steps": [
{"if": "n <= 1", "then": [{"return": 1}]},
{"let": "sub", "call": "factorial", "with": {"n": "n - 1"}},
{"return": "n * sub"}
]
}
},
"steps": [
{"let": "result", "call": "factorial", "with": {"n": "10"}},
{"return": "result"}
]
}{
"name": "my_api",
"server": {"port": 3000},
"functions": {
"listUsers": {
"params": {"request": "map"},
"steps": [
{"return": {"value": {"status": 200, "body": [
{"id": 1, "name": "Alice"},
{"id": 2, "name": "Bob"}
]}}}
]
}
},
"routes": [
{"method": "GET", "path": "/api/users", "handler": "listUsers"}
]
}go-json serve api.json
# Server running at http://localhost:3000
# Swagger UI at http://localhost:3000/docs{
"name": "fetch_and_save",
"import": {"http": "io:http", "fs": "io:fs"},
"steps": [
{"let": "resp", "call": "http.get", "args": ["https://api.example.com/data"]},
{"call": "fs.write", "args": ["./data.json", "raw content here"]},
{"call": "fs.write", "with": ["'./result.json'", "toJSON(resp.body)"]},
{"return": "resp.body"}
]
}Three ways to call any function — choose based on your needs:
{"call": "http.get", "args": ["https://api.com"]}
{"call": "http.get", "with": ["url"]}
{"let": "r", "expr": "http.get('https://api.com')"}go-json supports JSONC — JSON with comments and trailing commas:
go-json can orchestrate Python, JavaScript, and Go scripts from a single JSON program via the script: import prefix. Each script file is loaded by the matching runtime (detected by extension) and exposed as a callable module.
This requires the go-json-runtimes package, which provides the runtime engines (Goja for JS, QuickJS, Yaegi for Go, subprocess for Python). go-json core stays zero-dependency.
{
"name": "ml_pipeline",
"go_json": "1",
"import": {
"ml": "script:./plugins/predict.py",
"utils": "script:./helpers/format.js",
"fast": "script:./compute/process.go"
},
"steps": [
{"let": "prediction", "call": "ml.call", "with": ["'predict'", "input.features"]},
{"let": "formatted", "call": "utils.call", "with": ["'format'", "prediction"]},
{"let": "result", "call": "fast.call", "with": ["'process'", "formatted"]},
{"return": "result"}
]
}Each imported script exposes call(functionName, ...args) and exec(code) to your JSON program. Write your ML in Python, formatting in JavaScript, heavy compute in Go, and glue it all together in JSON.
package main
import (
"fmt"
gojson "github.com/bitcode-framework/go-json/runtime"
"github.com/bitcode-framework/go-json/stdlib"
)
func main() {
// Create runtime
reg := stdlib.DefaultRegistry()
rt := gojson.NewRuntime(
gojson.WithStdlib(reg.All()),
gojson.WithStdlibEnv(reg.EnvVars()),
)
// Compile program
program, err := rt.CompileFile("program.json")
if err != nil {
panic(err)
}
// Execute with input
result, err := rt.Execute(program, map[string]any{
"name": "Alice",
"age": 30,
})
if err != nil {
panic(err)
}
fmt.Println(result.Value)
fmt.Printf("Completed in %d steps, %v\n", result.Steps, result.Duration)
}rt := gojson.NewRuntime(
gojson.WithStdlib(reg.All()),
gojson.WithStdlibEnv(reg.EnvVars()),
gojson.WithIO(goio.HTTP(), goio.FS(), goio.SQL()),
)rt := gojson.NewRuntime(
gojson.WithStdlib(reg.All()),
gojson.WithStdlibEnv(reg.EnvVars()),
gojson.WithoutIO(),
gojson.WithExtension("myapp", runtime.Extension{
Functions: map[string]any{
"getUser": func(id string) (map[string]any, error) {
// your Go code here
return map[string]any{"name": "Alice"}, nil
},
},
}),
)| Document | Description |
|---|---|
| Features | Complete feature overview with capability matrix |
| Language | |
| Language Reference | Step types, syntax, type system, scoping rules |
| Built-in Functions | All 110+ functions (expr-lang + stdlib) |
| I/O & Server | |
| I/O Modules | HTTP, FS, SQL, Exec, MongoDB, Redis |
| Web Server | Routing, middleware, auth, templates, OpenAPI |
| Integration | |
| Embedding Guide | Go API, extensions, resource limits |
| CLI Reference | All commands and flags |
| Code Generation | Go/JS/Python codegen, CRUD generator, patterns |
┌─────────────────────────────────────────┐
│ Your Program │
│ (.json / .jsonc) │
└──────────────┬──────────────────────────┘
│
┌──────────────▼──────────────────────────┐
│ JSONC Pre-processor │
│ Strip comments, trailing commas │
└──────────────┬──────────────────────────┘
│
┌──────────────▼──────────────────────────┐
│ Parser │
│ JSON → AST nodes │
└──────────────┬──────────────────────────┘
│
┌──────────────▼──────────────────────────┐
│ Import Resolver │
│ Resolve ./relative, stdlib:, io:, ext:,│
│ script: │
└──────────────┬──────────────────────────┘
│
┌──────────────▼──────────────────────────┐
│ Compiler │
│ Struct registration, validation, │
│ limit resolution → CompiledProgram │
└──────────────┬──────────────────────────┘
│
┌──────────────▼──────────────────────────┐
│ Virtual Machine │
│ Tree-walk interpreter with debug hooks │
│ Expressions via expr-lang/expr │
└─────────────────────────────────────────┘
Key design decisions:
- Compile-once, run-many — Programs compile to an immutable
CompiledProgram. Multiple goroutines can execute the same program concurrently. - Expression engine abstraction — The VM never calls expr-lang directly. All expressions go through the
ExprEngineinterface. - Safe by default — Resource limits (step count, call depth, loop iterations, timeout, memory proxies) enforced at every step.
- JSON-native — Programs are valid JSON (or JSONC). No custom syntax to learn beyond JSON.
| Repository | Description |
|---|---|
| go-json | This repo. JSON/JSONC programming language engine in Go |
| go-json-runtimes | Script runtime engines for go-json (Goja, QuickJS, Yaegi, Python subprocess) |
| ui-stencil-web-components | 119 Stencil Web Components for enterprise applications |
| ui-tauri | Tauri 2.0 native shell for desktop and mobile |
MIT
{ // Calculate discount based on customer tier "name": "discount_calculator", "go_json": "1", "functions": { "calculateDiscount": { "params": { "price": "float", "tier": "string", }, // trailing comma OK "returns": "float", "steps": [ {"_c": "Gold customers get 20% off"}, {"if": "tier == 'gold'", "then": [ {"return": "price * 0.8"} ]}, /* Silver customers get 10% off */ {"if": "tier == 'silver'", "then": [ {"return": "price * 0.9"} ]}, {"return": "price"} ] } }, "steps": [ {"let": "final_price", "call": "calculateDiscount", "with": { "price": "input.price", "tier": "input.tier" }}, {"return": "final_price"} ] }