README.org
February 15, 2026 · View on GitHub
#+TITLE: Yamson
A high-performance YAML/JSON parser for Common Lisp.
- Features
-
Full-featured \ Yamson aims to comply with YAML 1.2 (only parsing, no serialization, but contributions are welcome), while also supporting fast JSON parsing in a subset mode.
Almost all YAML 1.2 features have been implemented, with [[Incompatibilities with YAML 1.2][a few incompatibilities]].
-
High performance \ Yamson can parse YAML at speeds around 50MB/s and JSON at over 100MB/s on Intel® Core™ i7-11700K with SBCL.
-
Low memory footprint \ Yamson is optimized for memory usage during parsing, reducing unnecessary byte consing and GC pressure, making it suitable for real-time applications (such as game development).
-
Highly portable \ Yamson is theoretically compatible with any ANSI-conforming implementation, and has been tested to work on SBCL, CCL, ECL, Clasp, and CLISP.
-
Minimal dependencies \ Yamson has very few dependencies and does not rely on foreign libraries such as =libyaml=.
-
Streaming parsing support \ Input doesn't need to be fully loaded into memory in the first place, improving memory efficiency in scenarios such as reading from files.
- Installation Yamson and its dependencies are not yet available on Quicklisp. You will need to manually clone them into the =local-projects= directory under your Quicklisp installation.
Yamson depends on:
-
Usage #+BEGIN_SRC lisp CL-USER> (yamson:parse " key:
- value1
- value2") (("key" "value1" "value2"))
CL-USER> (yamson:parse "
key: [&1 value, *1]
..." :mode :yaml-multidoc) ((("key" "value" "value")) :NULL)
CL-USER> (yamson:parse " a: 1 b: 2 c: 3") (("a" . 1) ("b" . 2) ("c" . 3))
CL-USER> (yamson:parse " a: 1 b: 2 c: 3" :mapping (alexandria:rcurry #'alexandria:alist-hash-table :test #'equal)) #<HASH-TABLE :TEST EQUAL :COUNT 3 {1202B6CAD3}>
CL-USER> (yamson:parse "
- ~
- null
- " :sequence (lambda (list) (coerce list 'simple-vector)) :null (constantly (vector))) #(#() #() #())
CL-USER> (yamson:parse "{"a":1} ..." :mode :json :junk-allowed t) (("a" . 1))
CL-USER> (yamson:parse "!intern SYMBOL" :tags (list (lambda (tag value) (when (string= tag "intern") (values (intern value) t))))) SYMBOL #+END_SRC
-
Incompatibilities with YAML 1.2 The following are known implemented features that are incompatible with the YAML 1.2 specification:
-
Anchors or tags cannot be applied to a sequence at the same indentation level as its parent mapping:
#+BEGIN_SRC yaml object: !!seq
- 1
- 2
- 3 #+END_SRC
To work around this, you must indent the sequence to the next level:
#+BEGIN_SRC yaml object: !!seq - 1 - 2 - 3 #+END_SRC
-
Tags do not influence how the parser interprets the subsequent object. For example:
#+BEGIN_SRC yaml !!str 1e3 #+END_SRC
This will yield
"1000.0"instead of"1e3", since1e3is first parsed as a number and then converted to a string. -
It is not possible to create a self-referential structure using anchors and aliases. For example:
#+BEGIN_SRC yaml &1 [1, 2, 3, *1] #+END_SRC
This fails because
&1does not take effect until after[1, 2, 3, *1]has been fully parsed.