Skip to content

Transpiler Usage Guide

The JSSON transpiler is the engine that converts your clean JSSON syntax into valid JSON, YAML, TOML, or TypeScript. Let’s explore how it works and how to use it! ⚙️

The transpiler follows a three-stage pipeline:

JSSON Source → Lexer → Parser → Transpiler → Output

Breaks your JSSON into tokens:

name = João

Becomes:

IDENT("name") ASSIGN IDENT("João")

Creates an Abstract Syntax Tree:

Program
└── AssignmentStatement
├── name: "name"
└── value: StringLiteral("João")

Converts the AST to the target format (JSON, YAML, etc.):

{
"name": "João"
}

The easiest way:

Terminal window
# Default (JSON)
jsson -i input.jsson -o output.json
# YAML
jsson -i input.jsson -f yaml
# TypeScript
jsson -i input.jsson -f ts

Use JSSON as a library in your Go code:

package main
import (
"fmt"
"jsson/internal/lexer"
"jsson/internal/parser"
"jsson/internal/transpiler"
)
func main() {
// Your JSSON source
source := `
app {
name = "My App"
version = "1.0.0"
}
`
// Step 1: Lex
l := lexer.New(source)
// Step 2: Parse
p := parser.New(l)
program := p.ParseProgram()
// Check for parse errors
if len(p.Errors()) > 0 {
for _, err := range p.Errors() {
fmt.Println(err)
}
return
}
// Step 3: Transpile
// New(program, workingDir, includeMode, sourceFile)
t := transpiler.New(program, ".", "keep", "main.jsson")
// Transpile to JSON
json, err := t.Transpile()
if err != nil {
fmt.Println("Transpile error:", err)
return
}
fmt.Println(string(json))
}
package main
import (
"fmt"
"os"
"path/filepath"
"jsson/internal/lexer"
"jsson/internal/parser"
"jsson/internal/transpiler"
)
func transpileFile(inputPath, outputPath string) error {
// Read input file
content, err := os.ReadFile(inputPath)
if err != nil {
return err
}
// Lex and parse
l := lexer.New(string(content))
l.SetSourceFile(inputPath) // For better error messages
p := parser.New(l)
program := p.ParseProgram()
if len(p.Errors()) > 0 {
for _, err := range p.Errors() {
fmt.Println(err)
}
return fmt.Errorf("parse errors")
}
// Transpile
workingDir := filepath.Dir(inputPath)
t := transpiler.New(program, workingDir, "keep", inputPath)
json, err := t.Transpile()
if err != nil {
return err
}
// Write output
return os.WriteFile(outputPath, json, 0644)
}

JSSON currently supports transpilation to:

  • JSON (Default) — For APIs and general config
  • YAML — For Kubernetes, CI/CD, and cloud infrastructure
  • TOML — For Rust/Go/Python configuration
  • TypeScript — For type-safe frontend constants

In the Go API, use the specific method for your desired format:

// JSON
json, _ := t.Transpile()
// YAML
yaml, _ := t.TranspileToYAML()
// TOML
toml, _ := t.TranspileToTOML()
// TypeScript
ts, _ := t.TranspileToTypeScript()

JSSON handles files efficiently:

  • Small files (< 1KB): Instant
  • Medium files (1-100KB): < 100ms
  • Large files (> 100KB): < 1s

The transpiler loads the entire file into memory. For very large files (> 10MB), consider:

  1. Splitting with includes
  2. Processing in chunks

1. Use includes for large configs:

// Instead of one 1000-line file
include "users.jsson" // 200 lines
include "products.jsson" // 300 lines
include "settings.jsson" // 500 lines

2. Avoid deeply nested structures:

// This is fine
user {
profile {
settings {
theme = dark
}
}
}
// This might be slow (10+ levels deep)
a { b { c { d { e { f { g { h { i { j {
value = deep
}}}}}}}}}}

3. Use template arrays efficiently:

// Good - 1000 users
users [
template { name, email }
// ... 1000 rows
]
// Better - split into multiple files
include "users-1-500.jsson"
include "users-501-1000.jsson"

The transpiler provides detailed error messages:

Lex goblin: config.jsson:15:8 — Illegal character: '@'
Parse wizard: config.jsson:20:5 — Unexpected token: expected '=', got '{'
Transpiler gremlin: config.jsson:25:10 — Undefined reference: 'config.port'

See the Errors & Debugging guide for details!

You can modify the AST before transpiling:

// Example: Add a timestamp to all objects
func addTimestamp(program *ast.Program) {
for _, stmt := range program.Statements {
if assign, ok := stmt.(*ast.AssignmentStatement); ok {
if obj, ok := assign.Value.(*ast.ObjectLiteral); ok {
// Add timestamp field
obj.Pairs["_timestamp"] = &ast.StringLiteral{
Value: time.Now().Format(time.RFC3339),
}
}
}
}
}
// Use it
program := p.ParseProgram()
addTimestamp(program)
t := transpiler.New(program, ".", "keep", "main.jsson")
json, _ := t.Transpile()
package main
import (
"net/http"
"io"
"jsson/internal/lexer"
"jsson/internal/parser"
"jsson/internal/transpiler"
)
func transpileHandler(w http.ResponseWriter, r *http.Request) {
// Read JSSON from request body
body, _ := io.ReadAll(r.Body)
// Transpile
l := lexer.New(string(body))
p := parser.New(l)
program := p.ParseProgram()
if len(p.Errors()) > 0 {
http.Error(w, p.Errors()[0], http.StatusBadRequest)
return
}
t := transpiler.New(program, ".", "keep", "request.jsson")
json, err := t.Transpile()
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", "application/json")
w.Write(json)
}
func main() {
http.HandleFunc("/transpile", transpileHandler)
http.ListenAndServe(":8080", nil)
}

The transpiler is the heart of JSSON — now you know how it works! ⚙️