A complete Clojure reader and an EDN-only reader, works with Clojure versions >= 1.3.0
- Rationale
- Public API
- Releases and Dependency Information
- Example Usage
- Differences from LispReader.java
- Changelog
- Developer Information
- License
clojure.tools.reader offers all functionality of the reader from clojure-1.5.0, and more.
This means safer read/read-string, an edn-only reader, tagged-literals support, default-data-reader-fn support for every Clojure version >=1.3.0
For a list of additional features of the reader, read Differences from LispReader.java
Moreover, by using reader types from clojure.tools.reader.reader-types, if using an IndexingReader, column info is available and both line and column metadata is attached not only to lists, but to symbols, vectors and maps too, when additional debugging info is needed (note that the edn reader doesn't add any line/column metadata at all).
Note that it uses ex-info which is available on clojure.core only from clojure-1.4.0.
If using clojure-1.3.0 and needing access to ex-data, use clojure.tools.reader.impl.utils/ex-data
There are four public namespaces:
- clojure.tools.reader.reader-types offers protocols, implementations and convenient function helpers for some reader types.
- Protocols:
- Types:
- Types Constructor Functions:
- Functions:
- clojure.tools.reader.edn offers a feature-complete EDN reader, whose API matches clojure.edn's one, those functions are safe.
- Functions:
- clojure.tools.reader offers a feature-complete clojure reader, whose API matches clojure.core's one, those functions are unsafe and may allow code execution if not used properly.
- Functions:
- Macros:
- syntax-quote
- Vars:
- clojure.tools.reader.default-data-readers offers implementations for the #inst and #uuid tagged literals, copied from the clojure source.
Refer to docstrings in each namespace and to the project's autodoc for more documentation.
Latest stable release: 0.7.4
Leiningen dependency information:
[org.clojure/tools.reader "0.7.4"]Maven dependency information:
<dependency>
<groupId>org.clojure</groupId>
<artifactId>tools.reader</artifactId>
<version>0.7.4</version>
</dependency>To read data structures, functions from clojure.tools.reader.edn should be used, since those are safe and don't allow any code execution at all.
Note that since no code-execution is permitted, reader literals are also disabled.
(require '[clojure.tools.reader.edn :as edn])
;=> nil
(edn/read-string "1")
;=> 1
(edn/read-string "#inst \"2010-11-12T13:14:15.666\"")
;=> #inst "2010-11-12T13:14:15.666-00:00"
(let [my-unknown (fn [tag val] {:unknown-tag tag :value val})]
(edn/read-string {:default my-unknown} "#foo bar"))
;=> {:unknown-tag foo, :value bar}
(edn/read-string {:readers {'foo (constantly 1)}} "#foo bar")
;=> 1To switch from using clojure.core/read-string to clojure.tools.reader.edn/read-string in your projects, put this in your namespace declaration:
(:refer-clojure :exclude [read read-string])
(:use [clojure.tools.reader.edn :only [read read-string]])If (and only if) reading from a trusted source, and advanced features that need some level of code-execution during read are needed, functions from clojure.tools.reader should be used.
(require '[clojure.tools.reader :as r])
;=> nil
(r/read-string "1")
;=> 1
;; WARNING!
(r/read-string "#=(+ 1 2)")
;=> 3
(binding [r/*read-eval* false]
(r/read-string "#=(+ 1 2)))
=> ExceptionInfo #= not allowed when *read-eval* is falseTo switch from using clojure.core/read-string to clojure.tools.reader/read-string in your projects, put this in your namespace declaration:
(:refer-clojure :exclude [read read-string *default-data-reader-fn* *read-eval* *data-readers*])
(:use [clojure.tools.reader :only [read read-string *default-data-reader-fn* *read-eval* *data-readers*]])Reader types example usage:
(require '[clojure.tools.reader.reader-types :as t])
;=> nil
(def reader (t/string-push-back-reader "1"))
;=> #'user/reader
(t/read-char reader)
;=> \1
(t/unread reader \a)
;=> \a
(t/peek-char reader)
;=> \a
(t/read-char reader)
;=> \a
(t/read-char reader)
;=> nilNote that the pushback buffer is of dimension 1 by default, and an exception will be thrown if trying to unread more chars than the pushback buffer dimension.
Every predefined reader type has an additional arity that allows to specify the pushback buffer dimension.
(def reader (t/string-push-back-reader "" 2))
;=> nil
(t/unread reader \a)
;=> \a
(t/unread reader \b)
;=> \b
(t/read-char reader)
;=> \b
(t/read-char reader)
;=> \a
(t/read-char reader)
;=> nilThere are small differences from clojure.lang.LispReader:
readthrows anex-infofor almost every exception, whereasclojure.lang.LispReader/readthrows aReaderExceptionwrapping the causing exception.readis capable of reading\xescaped charsreadis capable of readingInfinity+Infinity-InfinityandNaNas per #CLJ-1074readis capable of reading literal tags containing periods, fixing #CLJ-1100readis capable of reading the symbol / with an explicit namespace, e.g. foo//, whereasclojure.lang.LispReader/readthrows an exception. Refer to #CLJ-873. Except for this special case,readthrows an exception if a symbol contains more than one / character, whereasclojure.lang.LispReader/readallows them, returning a symbol with one or more / characters in its namespace name.clojure.tools.reader/readadds additional line/column info to symbols, vectors and maps when possibleclojure.tools.reader.reader-types/read-linehas an additional arity with which is possible to specify the reader to read from
- Release 0.6.0 on Feb 03, 2013
- Initial release.
- Release 0.6.2 on Feb 04, 2013
- Add line/column metadata on vectors, maps and symbols
- Release 0.6.4 on Feb 08, 2013
- Fix Unicode char reading
- Add *default-data-reader-fn* support
- Add an EDN-only reader
- Disable record literals reading when *read-eval* is bound to false
- Made % a symbol constituent char
- Made the EDN reader API match the clojure.edn one
- Release 0.6.5 on Feb 09, 2013
- Fixed reading @ ~ and `
- Release 0.7.0 on Feb 14, 2013
- Fixed #TRDR-1 by @jafingerhut
- Made compatible with clojure-1.3.0
- Decoupled from clojure.core vars (*read-eval*, *default-data-reader-fn*, *data-readers*)
- clojure.tools.reader/read-string and clojure.tools.reader.edn/read-string return nil if string is nil or empty
- Added comprehensive docstrings
- Release 0.7.1 on Mar 02, 2013
- Added the syntax-quote macro to the public API
- Release 0.7.2 on Mar 02, 2013
- Fixed evaling read objects for clojure 1.5
- Release 0.7.3 on Mar 08, 2013
- AOT compile only ExceptionInfo.
- Release 0.7.4 on Apr 19, 2013
- Fixed docstrings position and typos
- Fixed a bug that would have prevented future alpha versions of clojure to have column metadata
- Made symbols containing two consecutive ':' illegal, as per clojure.org
- Made symbols containing two consecutive '/' illegal
- Removed reflection warnings
Copyright © Nicola Mometto, Rich Hickey & contributors.
Licensed under the EPL. (See the file epl.html.)