Malli Users Start Here¶
Balli keeps Malli's schema-as-data workflow while adapting runtime details to Basilisp and Python.
Same Mental Model¶
Use plain data schemas:
[:map
[:id :uuid]
[:name [:string {:min 1}]]
[:roles [:set :keyword]]]
Validate, explain, transform, generate, and export from the same schema:
(require '[balli.core :as b])
(require '[balli.error :as be])
(require '[balli.generator :as bg])
(require '[balli.openapi :as openapi])
(require '[balli.transform :as bt])
(def user-schema
[:map {:closed true}
[:id :uuid]
[:name [:string {:min 1}]]
[:roles [:set :keyword]]])
(def decoded
(b/decode user-schema
{:id "550e8400-e29b-41d4-a716-446655440000"
:name "Ada"
:roles ["admin"]}
(bt/json-api-transformer)))
(b/validate user-schema decoded)
(be/humanize (b/explain user-schema decoded))
(bg/generate user-schema {:seed 1})
(openapi/schema user-schema)
Common Mappings¶
| Malli idea | Balli entry point |
|---|---|
m/validate |
balli.core/validate |
m/explain |
balli.core/explain |
me/humanize |
balli.error/humanize |
m/decode / m/encode |
balli.core/decode / balli.core/encode |
mt/string-transformer |
balli.transform/string-transformer |
mt/json-transformer |
balli.transform/json-transformer |
| schema registry | balli.registry/registry |
malli.util map helpers |
balli.util |
malli.provider |
balli.provider/provide |
| JSON Schema / OpenAPI | balli.json-schema, balli.openapi, balli.swagger |
Python Boundary Presets¶
Balli adds presets for common Python-hosted boundaries:
env-transformerfor environment/CLI config mapsquery-params-transformerfor query and form parameter mapsjson-api-transformerfor JSON API request and response bodies
These are ordinary transformers, so they can still be composed with
balli.transform/transformer when a boundary needs custom behavior.
Differences To Expect¶
- Balli is Basilisp/Python, not Clojure/JVM or ClojureScript.
- Python type predicates define scalar behavior. For example, Balli keeps int and float semantics aligned with Python/Basilisp.
- Safe schema serialization uses registered function references instead of evaluating serialized code.
- Some ecosystem integrations are examples or data exports rather than direct ports of Clojure libraries.
For a full matrix, see Balli vs Malli and Malli Compatibility.