
Sindre 发布面向人类的配置格式 SOML
来源标题:SOML – A Config Format for Humans
SOML(Sindre's Objectively Marvelous Language)是一种无需大括号和引号、以换行代替逗号、可随处加注释的配置格式。其类型由语法而非内容决定,日期、时间戳、时长均为原生值,路径和正则无需转义。作者称其兼顾 JSON 的严格性与 YAML 的可读性,并提供统一规范形式和共享一致性测试套件。
以下正文同步自 Hacker News,版权归原站所有,已转换为易读排版。
A config format for humans
SOML is short for Sindre's Objectively Marvelous Language.
SOML is a config format that is pleasant to write and easy to read. The top level needs no braces, keys need no quotes, line breaks replace commas, and comments go almost anywhere. A value's type comes from its syntax, never from its content, so what you see is what you get: '123' is a string and 123 is an int. Dates like 2026-09-19, instants like 2026-09-19T14:00:00Z, and durations like 30s are real values, so nobody has to guess the unit of timeout: 30. Paths and regexes need no escaping, and prose goes in block strings. One canonical form and a shared conformance suite mean every implementation reads your file the same way. JSON has the strictness but not the comfort: quotes, commas, and braces everywhere, and no comments. YAML has the comfort but not the clarity: - list markers, nested indentation, and types guessed from content, so country: no becomes false and version: 3.10 becomes 3.1. SOML gives you the comfort and the strictness, without the guessing.
name: 'api-gateway' port: 8080 # The load balancer expects this port. timeout: 30s launch-date: 2027-09-19 windows-path: 'C:\Users\sindre\dev' description: ''' Terminates TLS. Routes requests to internal services. ''' allowed-origins: [ 'https://example.com' 'https://example.org' ]
The same in JSON:
{ "name": "api-gateway", "port": 8080, "timeout": 30, "launch-date": "2027-09-19", "windows-path": "C:\Users\sindre\dev", "description": "Terminates TLS.\nRoutes requests to internal services.", "allowed-origins": [ "https://example.com", "https://example.org" ] }
Objectives
SOML is a data format for files that people write and read. It is JSON without the noise, and with comments. It keeps JSON's tree of objects and arrays and its strictness, and adds literal strings, block strings, dates, instants, and durations.
Its design rests on one rule: a value's type comes from its syntax, never from its content. '123' is a string and 123 is an int. Nothing is ever retyped by inspecting it.
Less noise than JSON, and comments. Keys need no quotes, even with dashes, a line break replaces a comma, and the top level needs no braces. Comments are allowed wherever whitespace may go.
What you see is the type. A string always has quotes, and a value without quotes must be a number, a date, an instant, a duration, or a keyword, or the file has an error. So country: no is an error rather than false, and '10.20' and 10.20 are a string and a float, exactly as written.
Strict where JSON is vague. Duplicate keys, lone surrogates, and numbers out of range are errors, not behavior that each parser decides. An int is exact to 64 bits, and 3 and 3.0 stay different types.
Pleasant to write. Literal strings, so paths and regexes need no escaping, and dedented block strings for prose.
Dates, instants, and durations are values. 2026-09-19 is a calendar date, 2026-09-19T14:00:00Z is an instant, and 1h30m is a duration, so no reader has to parse a string or guess a unit.
Indentation is free. Braces and line breaks give the structure, so tabs, spaces, and copy and paste never change what a file means, except inside a block string, where indentation is text.
One canonical form. Equal values give equal bytes, for hashing, signing, and comparing. A separate formatter keeps your comments, member order, and the spelling of each value. Its rules are part of the spec, so every conforming formatter gives the same output for the same file.
Small and tested. The grammar is one pass with no lookahead, and every implementation runs the language-neutral conformance suite of nearly 1000 cases, so every implementation reads a file the same way.
Example
/* Everything SOML can express, in one document. A document may also be a top-level array. */
Keys are bare. Dashes are allowed, so no key needs quotes.
name: 'soml' launch-date: 2027-09-19 released-at: 2026-09-19T14:00:00Z 'the name': 'quotes are the escape hatch, when a key needs spaces' 404: 'and a key may begin with a digit'
Strings: '...' is literal, "..." is escaped. Use ' by default.
regex: '^\d{4}-\d{2}-\d{2}$' windows-path: 'C:\Users\sindre\dev' shell: 'echo "$HOME" | tr -d "\n"' escaped: "line one\nline two\t"quoted"\u{1f600}"
Block strings are dedented by the closing delimiter's column.
description: ''' A block string keeps its line breaks. The leading tab of each line is stripped, because the closing delimiter sits at one tab. '''
Numbers: int and float are different types.
replicas: 3 ratio: 0.75 budget: 1_000_000 mask: 0b1010_1100 permissions: 0o644 color: 0xFF8800 flags: 0x00FF limit: infinity floor: -infinity
Booleans and null.
drained: false owner: null
Durations: exact, in h, m, s, ms, us, and ns.
retry-after: 1m30s
Arrays. A comma or a line break separates items.
labels: ['prod', 'eu-west', 'canary'] matrix: [[1, 2], [3, 4]] mixed: [1, 'two', true, null]
Objects. The top-level object needs no braces.
pool: { min: 2 max: 16 }
Records in arrays. Braces are required, and that is deliberate.
maintainers: [ {name: 'Sindre Sorhus', email: 'sindresorhus@gmail.com'} {name: 'Random Person', email: 'person@example.com'} ]
Line comments, and block comments, wherever whitespace may go.
Inline objects and one-line braced documents work too:
healthcheck: {path: '/health', interval: 10s, grace: 1.5s}
Why not YAML?
SOML keeps what I like about YAML: comments, no braces around the file, no commas at the ends of lines, and keys without quotes. It removes what hurts: in YAML, the content of a value decides its type. In SOML, the syntax decides, so 'no' is a string, 3.10 is a float, and 2 is an int, in every implementation.
SOML keeps what TOML gets right: predictable types, literal strings, insignificant indentation, and duplicate keys as errors. It removes what hurts: table rules where a key's meaning depends on what came before it, and values that parsers silently round, truncate, or read differently. A SOML file means one thing, no matter where a line sits or which parser reads it.
JSON is unambiguous but noisy to write: the file needs braces around it, every item needs a comma, every key needs quotes, and there are no comments. YAML is pleasant to write but ambiguous to read. SOML keeps JSON's data model and strictness, and also decides what JSON leaves to each implementation. From YAML, it takes comments, multi-line strings, and a top level with no braces or commas, but not implicit typing, significant indentation, aliases, or tags. From TOML, it takes literal strings and the split between int and float, but it allows a top-level array and has no table headers or dotted keys.
See the full comparison with JSON, JSON5, JSONC, TOML, YAML, and other formats, including where another format is the better choice.
The format is defined in the specification, which also gives the reason for each decision. The FAQ gives short answers to common questions, such as why SOML has durations and separate int and float types.
JavaScript (the reference implementation)
Swift
Rust
Python
Go
Ruby
C++
C
C#
Java
Kotlin
Dart
PHP
Zsh
Tools
ESLint plugin
Prettier plugin
highlight.js syntax highlighting
Prism syntax highlighting (👍 the PR to show your support)
Editor plugins
Visual Studio Code
Sublime Text
TextMate
Apps
SOML Editor - macOS app to view and edit SOML files and Quick Look support
Fun
soml-typescript-types - SOML parser, encoder, and canonicalizer written entirely in TypeScript types, with zero runtime code
Linting
Use eslint-soml with eslint-plugin-unicorn for additional lint rules. Unicorn provides a recommended-soml preset.
The MIT license applies to the specification itself. You may freely implement this specification without including or referencing the license.
正文由 探How 从来源站点 RSS 同步,内容未经改写;遇到排版缺失或需要图片、视频时请以原文为准。