RFC 9651 Structured Field Values for HTTP.
See the project website for info on motivation and design: https://github.com/outskirtslabs/sfv
This ns provides parsing and serialization of Structured Fields containing Items, Lists, and Dictionaries with Parameters. Returns precise AST representations that round-trip byte-for-byte with RFC 9651 strings.
Primary functions: parse, parse-item, parse-list, parse-dict,
serialize
s-or-bytes: Input string or byte array (decoded as ascii) containing HTTP field valuefield-type: One of :item, :list, or :dict specifying the top-level structure:bare: The raw value within an Item (Integer, Decimal, String, Token, Byte Sequence, Boolean, Date, or Display String)Each Item's :bare is one of these RFC 9651 types:
| SFV type | Header | AST example | Clojure type (:value) |
|---|---|---|---|
| Integer | 42, -17, 999999999999999 | {:type :integer :value 1618884473} | long |
| Decimal | 3.14, -0.5 | {:type :decimal :value 3.14M} | BigDecimal |
| String | " hello world " | {:type :string :value " hello "} | java.lang.String |
| Token | simple-token | {:type :token :value " simple-token "} | String |
| Byte Sequence | :SGVsbG8=: | {:type :bytes :value <platform bytes>} | byte[] |
| Boolean | ?1 / ?0 | {:type :boolean :value true} | true / false |
| Date | @1659578233 | {:type :date :value 1659578233} | epoch seconds as long |
| Display String | %" Gr%c3%bc%c3%9fe " | {:type :dstring :value " Grüße "} | String (percent-decoded, validated) |
RFC 9651 Structured Field Values for HTTP.
See the project website for info on motivation and design:
<https://github.com/outskirtslabs/sfv>
This ns provides parsing and serialization of Structured Fields containing
Items, Lists, and Dictionaries with Parameters. Returns precise AST
representations that round-trip byte-for-byte with RFC 9651 strings.
Primary functions: [[parse]], [[parse-item]], [[parse-list]], [[parse-dict]],
[[serialize]]
## Conventions
- `s-or-bytes`: Input string or byte array (decoded as ascii) containing HTTP field value
- `field-type`: One of `:item`, `:list`, or `:dict` specifying the top-level structure
- `:bare`: The raw value within an Item (Integer, Decimal, String, Token, Byte Sequence, Boolean, Date, or Display String)
## Primitive Types
Each Item's `:bare` is one of these RFC 9651 types:
| SFV type | Header | AST example | Clojure type (`:value`) |
|----------------|--------------------------------|--------------------------------------------|---------------------------------------|
| Integer | `42`, `-17`, `999999999999999` | `{:type :integer :value 1618884473}` | `long` |
| Decimal | `3.14`, `-0.5` | `{:type :decimal :value 3.14M}` | `BigDecimal` |
| String | `" hello world "` | `{:type :string :value " hello "}` | `java.lang.String` |
| Token | `simple-token` | `{:type :token :value " simple-token "}` | `String` |
| Byte Sequence | `:SGVsbG8=:` | `{:type :bytes :value <platform bytes>}` | `byte[]` |
| Boolean | `?1` / `?0` | `{:type :boolean :value true}` | `true` / `false` |
| Date | `@1659578233` | `{:type :date :value 1659578233}` | epoch seconds as `long` |
| Display String | `%" Gr%c3%bc%c3%9fe "` | `{:type :dstring :value " Grüße "}` | `String` (percent-decoded, validated) |
(parse field-type s-or-bytes)Parse a Structured Field of the given field-type.
Takes a field-type (:list, :dict, or :item) and a string or byte array.
Returns an AST representation following RFC 9651.
(parse :item "42")
;; => {:type :item :bare {:type :integer :value 42} :params []}
(parse :dict "max-age=3600, must-revalidate")
;; => {:type :dict :entries [["max-age" {...}] ["must-revalidate" {...}]]}
Parse a Structured Field of the given `field-type`.
Takes a `field-type` (`:list`, `:dict`, or `:item`) and a string or byte array.
Returns an AST representation following RFC 9651.
```clojure
(parse :item "42")
;; => {:type :item :bare {:type :integer :value 42} :params []}
(parse :dict "max-age=3600, must-revalidate")
;; => {:type :dict :entries [["max-age" {...}] ["must-revalidate" {...}]]}
```(parse-dict s-or-bytes)Parse a Structured Field Dictionary from s-or-bytes.
Returns a Dictionary AST with :type :dict and :entries as ordered key-value pairs.
Each entry maps from a key to either an Item or Inner List.
(parse-dict "max-age=3600, must-revalidate")
;; => {:type :dict :entries [["max-age" {...}] ["must-revalidate" {...}]]}
Parse a Structured Field Dictionary from `s-or-bytes`.
Returns a Dictionary AST with `:type :dict` and `:entries` as ordered key-value pairs.
Each entry maps from a key to either an Item or Inner List.
```clojure
(parse-dict "max-age=3600, must-revalidate")
;; => {:type :dict :entries [["max-age" {...}] ["must-revalidate" {...}]]}
```(parse-item s-or-bytes)Parse a Structured Field Item from s-or-bytes.
Returns an Item AST with :type :item, :bare value, and :params Parameters.
The bare value can be Integer, Decimal, String, Token, Byte Sequence, Boolean, Date, or Display String.
(parse-item "42")
;; => {:type :item :bare {:type :integer :value 42} :params []}
(parse-item "pear;sweet")
;; => {:type :item :bare {:type :token :value "pear"} :params [["sweet" {...}]]}
Parse a Structured Field Item from `s-or-bytes`.
Returns an Item AST with `:type :item`, `:bare` value, and `:params` Parameters.
The bare value can be Integer, Decimal, String, Token, Byte Sequence, Boolean, Date, or Display String.
```clojure
(parse-item "42")
;; => {:type :item :bare {:type :integer :value 42} :params []}
(parse-item "pear;sweet")
;; => {:type :item :bare {:type :token :value "pear"} :params [["sweet" {...}]]}
```(parse-list s-or-bytes)Parse a Structured Field List from s-or-bytes.
Returns a List AST with :type :list and :members vector containing Items and Inner Lists.
(parse-list "apple, pear;sweet=true, orange")
;; => {:type :list :members [...]}
Parse a Structured Field List from `s-or-bytes`.
Returns a List AST with `:type :list` and `:members` vector containing Items and Inner Lists.
```clojure
(parse-list "apple, pear;sweet=true, orange")
;; => {:type :list :members [...]}
```(serialize x)Serialize a Structured Field AST x to its string representation.
Takes any parsed AST (Item, List, or Dictionary) and returns the RFC 9651 string.
(serialize {:type :item :bare {:type :integer :value 42} :params []})
;; => "42"
(serialize-list {:type :list :members [...]})
;; => "apple, pear;sweet=true, orange"
(serialize-dict {:type :dict :entries [["max-age" {...}] ["must-revalidate" {...}]]})
;; => "max-age=3600, must-revalidate"
Serialize a Structured Field AST `x` to its string representation.
Takes any parsed AST (Item, List, or Dictionary) and returns the RFC 9651 string.
```clojure
(serialize {:type :item :bare {:type :integer :value 42} :params []})
;; => "42"
(serialize-list {:type :list :members [...]})
;; => "apple, pear;sweet=true, orange"
(serialize-dict {:type :dict :entries [["max-age" {...}] ["must-revalidate" {...}]]})
;; => "max-age=3600, must-revalidate"
```cljdoc builds & hosts documentation for Clojure/Script libraries
| Ctrl+k | Jump to recent docs |
| ← | Move to previous article |
| → | Move to next article |
| Ctrl+/ | Jump to the search field |