Skip to content

Repository files navigation

go-json

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!"

Why go-json?

go-json fills a gap no existing tool covers: a general-purpose JSON programming language that is embeddable in Go applications.

ToolWhat It DoesWhat It Can't Do
jsonnetData templatingNo side effects, no I/O, no control flow
jqJSON transformationSingle-purpose, no general programming
AWS Step FunctionsCloud workflowsAWS-locked, no local execution
Node-REDIoT/integrationNode.js-dependent, visual-only
CEL / expr-langExpression evaluationExpressions 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.

Use Cases

  • 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

Installation

As a CLI tool

go install github.com/bitcode-framework/go-json/cmd/go-json@latest

As a Go library

go get github.com/bitcode-framework/go-json@latest

Requirements: Go 1.24+

Quick Start

1. Hello World

Create hello.json:

{
"name": "hello",
"go_json": "1",
"steps": [
{"let": "greeting", "value": "Hello, World!"},
{"return": "greeting"}
]
}
go-json run hello.json

2. With Input

Create 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}'

3. Functions & Recursion

{
"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"}
]
}

4. Web Server

{
"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

5. I/O Modules

{
"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')"}

6. JSONC Support (Comments!)

go-json supports JSONC — JSON with comments and trailing commas:

{
// 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"}
]
}

7. Script Plugins (Multi-Language)

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.

Embedding in Go

package main
import (
"fmt"
gojson "github.com/bitcode-framework/go-json/runtime""github.com/bitcode-framework/go-json/stdlib"
)
funcmain() {
// Create runtimereg:=stdlib.DefaultRegistry()
rt:=gojson.NewRuntime(
gojson.WithStdlib(reg.All()),
gojson.WithStdlibEnv(reg.EnvVars()),
)
// Compile programprogram, err:=rt.CompileFile("program.json")
iferr!=nil {
panic(err)
}
// Execute with inputresult, err:=rt.Execute(program, map[string]any{
"name": "Alice",
"age": 30,
})
iferr!=nil {
panic(err)
}
fmt.Println(result.Value)
fmt.Printf("Completed in %d steps, %v\n", result.Steps, result.Duration)
}

With I/O Modules

rt:=gojson.NewRuntime(
gojson.WithStdlib(reg.All()),
gojson.WithStdlibEnv(reg.EnvVars()),
gojson.WithIO(goio.HTTP(), goio.FS(), goio.SQL()),
)

With Custom Extensions

rt:=gojson.NewRuntime(
gojson.WithStdlib(reg.All()),
gojson.WithStdlibEnv(reg.EnvVars()),
gojson.WithoutIO(),
gojson.WithExtension("myapp", runtime.Extension{
Functions: map[string]any{
"getUser": func(idstring) (map[string]any, error) {
// your Go code herereturnmap[string]any{"name": "Alice"}, nil
},
},
}),
)

Documentation

DocumentDescription
FeaturesComplete feature overview with capability matrix
Language
Language ReferenceStep types, syntax, type system, scoping rules
Built-in FunctionsAll 110+ functions (expr-lang + stdlib)
I/O & Server
I/O ModulesHTTP, FS, SQL, Exec, MongoDB, Redis
Web ServerRouting, middleware, auth, templates, OpenAPI
Integration
Embedding GuideGo API, extensions, resource limits
CLI ReferenceAll commands and flags
Code GenerationGo/JS/Python codegen, CRUD generator, patterns

Architecture

 ┌─────────────────────────────────────────┐
│ 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 ExprEngine interface.
  • 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.

Related Repositories

RepositoryDescription
go-jsonThis repo. JSON/JSONC programming language engine in Go
go-json-runtimesScript runtime engines for go-json (Goja, QuickJS, Yaegi, Python subprocess)
ui-stencil-web-components119 Stencil Web Components for enterprise applications
ui-tauriTauri 2.0 native shell for desktop and mobile

License

MIT

About

General-purpose JSON/JSONC programming language engine in Go. 20 step types, 135+ functions, lambda expressions, structs, I/O modules, web server.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages