Jsson Docs
Guides

Transpiler Usage Guide

Learn how the JSSON transpiler works, how to use it programmatically, and how to extend it for custom output formats.

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! ⚙️

How It Works

The transpiler follows a three-stage pipeline:

JSSON Source → Lexer → Parser → Transpiler → Output

1. Lexer (Tokenization)

Breaks your JSSON into tokens:

name = João

Becomes:

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

2. Parser (AST Generation)

Creates an Abstract Syntax Tree:

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

3. Transpiler (Code Generation)

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

{
  "name": "João"
}

Using the Transpiler

Command Line

The easiest way:

# Default (JSON)
jsson -i input.jsson -o output.json

# YAML
jsson -i input.jsson -f yaml

# TypeScript
jsson -i input.jsson -f ts

Programmatic Usage (Go)

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))
}

Reading from Files

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)
}

Output Formats

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

Selecting Format

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()

Performance Considerations

File Size

JSSON handles files efficiently:

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

Memory Usage

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

  1. Splitting with includes
  2. Processing in chunks

Optimization Tips

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"

Error Handling

The transpiler provides detailed error messages:

Lex Errors

Lex goblin: config.jsson:15:8 — Illegal character: '@'

Parse Errors

Parse wizard: config.jsson:20:5 — Unexpected token: expected '=', got '{'

Transpile Errors

Transpiler gremlin: config.jsson:25:10 — Undefined reference: 'config.port'

See the Errors & Debugging guide for details!

Extending the Transpiler

Custom Transformations

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()

Integration Examples

Web Server

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)
}

What's Next?

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

On this page