Skip to main content

Stick And String (SAS 1.1)

A human-readable, deterministic data serialization format.

SAS is designed to be easy to read and write by hand, while remaining strict enough to parse unambiguously — no comma errors, no indentation-sensitivity, and full JSON interoperability.

# SAS 1.1 example
__sas_version__ -> "1.1"

server ::
    host -> "localhost"
    port -> 8080
    tags -> ["api" | "production"]
    tls  -> true
:: server

Install

Node.js / Browser

npm install stick-and-string

Python

pip install stick-and-string

Quick Start

JavaScript

import { parseSAS, sasToJSON, jsonToSAS } from 'stick-and-string';

// Parse SAS → JS object
const obj = parseSAS(`
server ::
    host -> "localhost"
    port -> 8080
:: server
`);
console.log(obj.server.port); // 8080

// SAS → JSON string
const json = sasToJSON(sasSource);

// JS object / JSON string → SAS
const sas = jsonToSAS({ host: 'localhost', port: 8080 });

CommonJS

const { parseSAS, sasToJSON, jsonToSAS } = require('stick-and-string');

Browser (ESM)

<script type="module">
  import { parseSAS } from './node_modules/stick-and-string/index.mjs';
</script>

Python

from sas_tools import parse_sas, sas_to_json, json_to_sas

# Parse SAS → dict
obj = parse_sas(open("config.sas").read())
print(obj["server"]["port"])  # 8080

# SAS → JSON string
json_str = sas_to_json(open("config.sas").read())

# dict → SAS string
sas = json_to_sas({"host": "localhost", "port": 8080})

CLI

Both packages install a sas command.

# Validate a SAS file
sas validate config.sas

# Convert SAS → JSON
sas to-json config.sas
sas to-json config.sas --output config.json
sas to-json config.sas --compact

# Convert JSON → SAS
sas to-sas data.json
sas to-sas data.json --output data.sas --no-version

# Round-trip check (great for CI)
sas roundtrip config.sas
sas roundtrip data.json

Format Overview

Key → Value pairs

name    -> "Alice"
port    -> 8080
enabled -> true
ratio   -> 3.14
nothing -> null

Block objects (named open/close)

server ::
    host -> "db.internal"
    port -> 5432
:: server

Inline objects (small, flat)

origin -> { lat -> 37.77 | lon -> -122.41 }

Inline arrays (scalars)

tags -> ["api" | "production" | "v2"]

Block arrays

hosts ::
    - "web1.internal"
    - "web2.internal"
:: hosts

Block arrays of objects

servers ::
    - ::
        host -> "a.local"
        port -> 8080
    :: -
    - ::
        host -> "b.local"
        port -> 9090
    :: -
:: servers

Multiline strings

description -> """
Line one.
Line two.
"""

Comments

# This is a comment
# Inline comments are NOT permitted

API Reference

JavaScript

Export Signature Description
parseSAS (source: string) → object Parse SAS document
sasToJSON (source, {indent, stripVersion}) → string SAS → JSON string
sasToObject (source) → object SAS → plain JS object
jsonToSAS (input, {versionHeader, indent}) → string object/JSON → SAS
SASParseError class Parse error with .lineNum
JSONToSASError class Serialization error with .path

Python

Export Signature Description
parse_sas (source: str) → dict Parse SAS document
sas_to_json (source, indent, strip_version) → str SAS → JSON string
sas_to_object (source) → dict SAS → Python dict
json_to_sas (input, version_header, indent) → str dict/JSON → SAS
SASParseError class Parse error with .line_num
JSONToSASError class Serialization error with .path

Error Codes

All errors include a line number. Parser errors are never silent.

Code Description
E01 Duplicate key in same scope
E02 Block closer mismatch or bare ::
E03 Unclosed block or multiline string at EOF
E04 Invalid escape sequence
E05 Invalid number (leading zero, +, NaN, etc.)
E06 Wrong-case boolean or null (True, NULL, …)
E07 Inline comment
E08 Missing spaces around ->
E09 Missing spaces around | in inline array/object
E10 Trailing |
E11 Non-scalar in inline array
E12 Nested inline object
E13 Key starting with -
E14 Mixed block content (array items + pairs)
E15 Anonymous closer outside array context

Publishing

npm

cd npm/
npm publish --access public

PyPI

cd pip/
pip install build twine
python -m build
twine upload dist/*

License

Copyright (c) 2025 Sourasish Das
Licensed under the Vexon Open-Control License (VOCL) 1.0.

Metadata

Release files for stick-and-string 1.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for stick-and-string 1.1.0
File Size Uploaded
stick_and_string-1.1.0.tar.gz 14.1 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for stick-and-string 1.1.0
File Interpreter ABI Platform
stick_and_string-1.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 28.3 kB

Release files / stick_and_string-1.1.0.tar.gz

Download URL stick_and_string-1.1.0.tar.gz
Size 14.1 kB
Tags Source
SHA-256 checksum
How to use checksums
b29b4a854a7c36364dda259b2dfd814edc01c27f3d949d640d9c2bae7ad7723b
BLAKE2b-256 checksum
How to use checksums
055702d18fcadf36f6d4e4887454a681412bf4c9c86885e110edce08686eaf16
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.14.3

Release files / stick_and_string-1.1.0-py3-none-any.whl

Download URL stick_and_string-1.1.0-py3-none-any.whl
Size 14.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
934e46d2ac507b89bd8e6fc9b29813ffe7d8f534ea7a69d1cfb99f63df90bacf
BLAKE2b-256 checksum
How to use checksums
8a457c5a3528a333f80e0271d80887f968afc010d797e8da744211436f611a34
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.14.3

Release history Release notifications | RSS feed

This release

1.1.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page