HackerReposA FIELD GUIDE TO OPEN SOURCE
ProSponsor the shelf♧ 0
← Back to top all-time
plumatic
schema
Clojure2013–2022
plumatic / schema

schema

Clojure(Script) library for declarative data description and validation

34Distinct people
40Mentions
1Explicit recommenders
2.5KGitHub stars
REPOSITORY AT A GLANCE

What to know before exploring

What it is

Clojure(Script) library for declarative data description and validation

GitHub

Where it is used

No documented product use was verified in the last source check.

What people are saying

I don't have nearly the breadth of experience in Clojure as the circleci guys, but I found that Prismatic's Schema [0] works well for me vs. core.typed. I can selectively…

numlocked used a recommendation phrase. One indexed comment matches. This is a phrase match, not a verdict.

No classified warning is attached to this page. Read the discussions before treating silence as approval.

Also in these discussions

Mentioned in the same Hacker News threads. That is not proof they are substitutes.

This week on Hacker News

Nov 8–Nov 15 UTC · Direct repository links and separately labeled related project stories. Indexed through 11/15/2026, 11:34:28 AM UTC.

No direct repository links were found in the indexed HN discussions over the past seven days. Older discussions are available below.

Mentions over time

HN mentions by year40 dated mentions

Observed mentions: 2013-09-05 16:49:14 UTC to 2022-10-05 02:30:45 UTC.

0369122013-01-01 00:00:00 UTC to 2014-01-01 00:00:00 UTC (exclusive): 2 mentions; 0 submissions, 2 comments20132014-01-01 00:00:00 UTC to 2015-01-01 00:00:00 UTC (exclusive): 6 mentions; 0 submissions, 6 comments2015-01-01 00:00:00 UTC to 2016-01-01 00:00:00 UTC (exclusive): 11 mentions; 0 submissions, 11 comments2016-01-01 00:00:00 UTC to 2017-01-01 00:00:00 UTC (exclusive): 8 mentions; 0 submissions, 8 comments2017-01-01 00:00:00 UTC to 2018-01-01 00:00:00 UTC (exclusive): 2 mentions; 0 submissions, 2 comments20172018-01-01 00:00:00 UTC to 2019-01-01 00:00:00 UTC (exclusive): 2 mentions; 0 submissions, 2 comments2019-01-01 00:00:00 UTC to 2020-01-01 00:00:00 UTC (exclusive): 2 mentions; 0 submissions, 2 comments2020-01-01 00:00:00 UTC to 2021-01-01 00:00:00 UTC (exclusive): 4 mentions; 0 submissions, 4 comments2021-01-01 00:00:00 UTC to 2022-01-01 00:00:00 UTC (exclusive): 1 mentions; 0 submissions, 1 comments2022-01-01 00:00:00 UTC to 2023-01-01 00:00:00 UTC (exclusive): 2 mentions; 0 submissions, 2 comments2022

Counts come from the repository’s dated source evidence. Index cutoff: 2026-11-02 08:16:59 UTC.

View mention counts and date ranges
UTC ranges include their start and exclude their end. Select a period to filter the source evidence.
PeriodStart (UTC)End (exclusive, UTC)MentionsSubmissionsComments
20132013-01-01 00:00:00 UTC2014-01-01 00:00:00 UTC202
20142014-01-01 00:00:00 UTC2015-01-01 00:00:00 UTC606
20152015-01-01 00:00:00 UTC2016-01-01 00:00:00 UTC11011
20162016-01-01 00:00:00 UTC2017-01-01 00:00:00 UTC808
20172017-01-01 00:00:00 UTC2018-01-01 00:00:00 UTC202
20182018-01-01 00:00:00 UTC2019-01-01 00:00:00 UTC202
20192019-01-01 00:00:00 UTC2020-01-01 00:00:00 UTC202
20202020-01-01 00:00:00 UTC2021-01-01 00:00:00 UTC404
20212021-01-01 00:00:00 UTC2022-01-01 00:00:00 UTC101
20222022-01-01 00:00:00 UTC2023-01-01 00:00:00 UTC202

From the project README

An excerpt from the repository, fetched Nov 13, 2026.

Read the project’s introduction
A Clojure(Script) library for declarative data description and validation. API docs. -- One of the difficulties with bringing Clojure into a team is the overhead of understanding the kind of data (e.g., list of strings, nested map from long to string to double) that a function expects and returns. While a full-blown type system is one solution to this problem, we present a lighter weight solution: schemas. (For more details on why we built Schema, check out this post.) Schema is a rich language for describing data shapes, with a variety of features: Data validation, with descriptive error messages of failures (targeted at programmers) Annotation of function arguments and return values, with optional runtime validation Schema-driven data coercion, which can automatically, succinctly, and safely convert complex data types (see the Coercion section below) Other Schema is also built into our plumbing and fnhouse libraries, which illustrate how we build services and APIs easily and safely with Schema Schema also supports experimental clojure.test.check data generation from Schemas, as well as completion of partial datums, features we've found very useful when writing tests as part of the schema-generators library Meet Schema A Schema is a Clojure(Script) data structure describing a data shape, which can be used to document and validate functions and data. (ns schema-examples (:require [schema.core :as s :include-macros true ;; cljs only ])) (s/defschema Data "A schema for a nested data type" {:a {:b s/Str :c s/Int} :d [{:e s/Keyword :f [s/Num]}]}) (s/validate Data {:a {:b "abc" :c 123} :d [{:e :bc :f [12.2 13 100]} {:e :bc :f [-1]}]}) ;; Success! (s/validate Data {:a {:b 123 :c "ABC"}}) ;; Exception -- Value does not match schema: ;; {:a {:b (not (instance? java.lang.String 123)), ;; :c (not (integer? "ABC"))}, ;; :d missing-required-key} The simplest schemas describe leaf values like Keywords, Numbers, and instances of Classes (on the JVM) and prototypes (in ClojureScript): ;; s/Any, s/Bool, s/Num, s/Keyword, s/Symbol, s/Int, and s/Str are cross-platform schemas. (s/validate s/Num 42) ;; 42 (s/validate s/Num "42") ;; RuntimeException: Value does not match schema: (not (instance java.lang.Number "42")) (s/validate s/Keyword :whoa) ;; :whoa (s/validate s/Keyword 123) ;; RuntimeException: Value does not match schema: (not (keyword? 123)) ;; On the JVM, you can use classes for instance? checks (s/validate java.lang.String "schema") ;; On JS, you can use prototype functions (s/validate Element (js/document.getElementById "some-div-id")) From these simple building blocks, we can build up more complex schemas that look like the data they describe. Taking the examples above: ;; list of strings (s/validate [s/Str] ["a" "b" "c"]) ;; nested map from long to String to double (s/validate {long {String double}} {1 {"2" 3.0 "4" 5.0}}) Since schemas are just data, you can also def them and reuse and compose them as you would expect: (def StringList [s/Str]) (def StringScores {String double}) (def StringScoreMap {long StringScores}) However, we encourage you to use s/defschema for this purpose to improve error messages: (s/defschema StringList [s/Str]) (s/defschema StringScores {String double}) (s/defschema StringScoreMap {long StringScores}) What about when things go bad? Schema's s/check and s/validate provide meaningful errors that look like the bad parts of your data, and are (hopefully) easy to understand. (s/validate StringList ["a" :b "c"]) ;; RuntimeException: Value does not match schema: ;; [nil (not (instance? java.lang.String :b)) nil] (s/validate StringScoreMap {1 {"2" 3.0 "3" [5.0]} 4.0 {}}) ;; RuntimeException: Value does not match schema: ;; {1 {"3" (not (instance? java.lang.Double [5.0]))}, ;; (not (instance? java.lang.Long 4.0)) invalid-key} See the More examples section below for more examples and explanation, or the custom Schemas types page for details on how Schema works under the hood. Beyond type hints If you've done much Clojure, you've probably seen code with documentation like this: (defprotocol TimestampOffsetter (offset-timestamp [this offset] "adds integer offset to stamped object and returns the result")) (defrecord StampedNames [^Long date names] ;; a list of Strings TimestampOffsetter (offset [this offset] (+ date offset))) (defn ^StampedNames stamped-names "names is a list of Strings" [names] (StampedNames. (str (System/currentTimeMillis)) names)) (def ^StampedNames example-stamped-names (stamped-names (map (fn [first-name] ;; takes and returns a string (str first-name " Smith")) ["Bob" "Jane"]))) Clojure's type hints make great documentation, but they fall short for complex types, often leading to ad-hoc descriptions of data in comments and doc-strings. This is better than nothing, but these ad hoc descriptions are often imprecise, hard to read, and prone to bit-rot. Schema provides macros s/defprotocol, s/defrecord, s/defn, s/def, and s/fn that help bridge this gap. These macros are just like their clojure.core counterparts, except they support arbitrary schemas as type hints on fields, arguments, and return values. This is a graceful extension of Clojure's type hinting system, because every type hint is a valid Schema, and Schemas that represent valid type hints are automatically passed through to Clojure. (s/defprotocol TimestampOffsetter (offset-timestamp :- s/Int [this offset :- s/Int])) (s/defrecord StampedNames [date :- Long names :- [s/Str]] TimestampOffsetter (offset [this offset] (+ date offset))) (s/defn stamped-names :- StampedNames [names :- [s/Str]] (StampedNames. (str (System/currentTimeMillis)) names)) (s/def example-stamped-names :- StampedNames (stamped-names (map (s/fn :- s/Str [first-name :- s/Str] (str first-name
Read the full README on GitHub

What Hacker News says

4 sources
One can check that something is a string and not a blank one. There are two different libraries that do it: https://github.com/plumatic/schema/blob/ddb54c87dea6926c6d73... https://github.com/clojure/spec.alpha/blob/eb49d429e85b6878a... Honestly I highly suspect that many, many "typing" solutions out there are plain ignorant of the whole spectrum of choices one can make, are tend to lean towards Java-like APIs out of that ignorance. This is not limited to Ruby, I also see it in TypeScript which is very much a contrived system for real-world usages while making little use of JS's dynamism.
In RBS, Ruby’s new type signature language
Not sure we have any talks about that specifically, but what I can say is that on the Clojure codebases: - We rely heavily on testing (unit tests, property-based/generative and integration) - We adopt a micro-services architecture, so most codebases are small enough that refactoring is easy, or sometimes we just replace the service altogether - We leverage Schema (https://github.com/plumatic/schema) and/or clojure.spec (https://clojure.org/guides/spec) to annotate functions and data schemas, but it's opt-in - We have static checking of data schemas across boundaries (e.g. checking data producers did not break consumers over HTTP or Kafka), which is where we found the most value (replaced complicated end-to-end tests)
In Nubank acquires Cognitect
Perhaps. I was trying to find something pithy to give as an example. It's difficult to express all the things about spec that feel off to me. I'll try to enumerate some: - verbosity (I think schema does this better https://github.com/plumatic/schema) - because it tries to not be about validating types of inputs and outputs, and rather treats everything as predicates, it tends to live in a grey area between type validation and unit-testing, and I think hinders both - it only helps at run-time - over-abundance of macro-usage
In State of Clojure 2020

MAKE YOURSELF AT HOME

A few shortcuts

/
Search the collection
?
Open this guide
Esc
Close dialogs and navigation

Your saved repositories and interests stay in this browser.