Skip to content

Clojure Guide — EDN: Extensible Data Notation

DodaTech Updated 2026-06-28 4 min read

In this tutorial, you will learn about Clojure Guide. We cover key concepts, practical examples, and best practices to help you master this topic.

EDN (Extensible Data Notation) is Clojure's native data serialization format designed for representing data structures as plain text, supporting the full richness of Clojure data types in a human-readable way.

What You'll Learn

  • What EDN is and how it differs from JSON and XML
  • EDN syntax for vectors, maps, sets, and keywords
  • Tagged literals for extensibility
  • Reading and writing EDN in Clojure

Why It Matters

EDN is Clojure's native data language, used for configuration files, data exchange, and even as a wire format for tools like Integrant and Arachne. Unlike JSON, EDN supports keywords, symbols, sets, and tagged literals natively. Durga Antivirus Pro uses EDN for rule configuration files.

Real-World Use

Clojure projects use EDN for project configuration (deps.edn), system configuration (Integrant), and data exchange between services. Tools like Leiningen and Cursive use EDN for configuration.

flowchart LR
    A["EDN Basics"] --> B["EDN Syntax"]
    B --> C["Tagged Literals"]
    C --> D["Reading/Writing"]
    D --> E["Real-World Uses"]
    A:::current --> B
    style A fill:#2563eb,stroke:#2563eb,color:#fff
    style B fill:#dbeafe,stroke:#2563eb,color:#1e40af
    style C fill:#dbeafe,stroke:#2563eb,color:#1e40af
    style D fill:#dbeafe,stroke:#2563eb,color:#1e40af
    style E fill:#f1f5f9,stroke:#94a3b8,color:#64748b

What is EDN?

EDN stands for Extensible Data Notation. It is a subset of Clojure data literal syntax designed specifically for data representation rather than code. This makes EDN safe to read from untrusted sources because it has no macro capability.

;; EDN data
{:name "Alice"
 :age 30
 :languages [:clojure :python :java]}

EDN vs JSON

Feature EDN JSON
Keywords :keyword Must use strings
Sets #{1 2 3} Not supported
Comments ; line comments Not supported
Tagged literals #inst "..." Not supported
Numbers 1/3, 32N Limited

EDN Data Types

;; Scalars
42        ; Long
3.14      ; Double
1/3       ; Ratio
32N       ; BigInteger
:keyword  ; Keyword
symbol    ; Symbol
true      ; Boolean
nil       ; Nil

;; Collections
[1 2 3]              ; Vector
#{:a :b :c}           ; Set
{:key "value"}        ; Map
(1 2 3)              ; List

Tagged Literals

Tagged literals extend EDN with custom types:

;; Built-in tagged literals
#inst "2024-01-15T10:00:00.000-00:00"   ; Instant
#uuid "f81d4fae-7dec-11d0-a765-00a0c91e6bf6"  ; UUID

;; Custom tagged literal
(defrecord Person [name age])
#myapp/person {:name "Alice" :age 30}

Reading EDN

(require '[clojure.edn :as edn])

;; Read from string
(edn/read-string "{:name \"Alice\" :age 30}")
;; => {:name "Alice", :age 30}

;; Read with a reader
(let [data (slurp "config.edn")]
  (edn/read-string data))

Writing EDN

(require '[clojure.pprint :as pp])

;; Print as EDN
(pr-str {:name "Alice" :age 30})
;; => "{:name \"Alice\", :age 30}"

;; Pretty print
(pp/pprint {:name "Alice"
            :languages [:clojure :python]
            :metadata {:version 2}})

EDN for Configuration

;; config.edn
{:database {:host "localhost"
            :port 5432
            :name "myapp"}
 :server {:port 8080
          :threads 4}
 :logging {:level :info
           :file "app.log"}}

Common Mistakes

1. Confusing EDN with Clojure code

EDN is a subset of Clojure data literals. It cannot contain function calls, macros, or arbitrary code. This is a safety feature.

2. Forgetting to require clojure.edn

Always use clojure.edn/read-string instead of read-string for untrusted data to avoid code execution.

3. Invalid keyword syntax

Keywords must start with a colon: :name not name:.

4. Mismatched brackets

EDN requires balanced delimiters. A missing closing bracket causes a read error.

5. Using commas as separators

Commas in EDN are treated as whitespace. They are optional but sometimes used for readability.

Practice Questions

1. What makes EDN different from JSON? EDN supports keywords, symbols, sets, ratios, tagged literals, and comments natively. It is a subset of Clojure data syntax.

2. How do tagged literals work? A tag is a symbol followed by a data literal. The tag tells the reader to construct a specific type from the data.

3. Why use clojure.edn/read-string instead of read-string? edn/read-string only reads data literals, not code. read-string can evaluate arbitrary code, creating a security risk.

Challenge: Design an EDN configuration format for a web application with database, Caching, and API settings.

FAQ

{{< faq question="Is EDN faster than JSON?" >}} EDN Parsing is generally slower than JSON in Clojure. For performance-critical data exchange, consider Transit or JSON with a specialized library. {{< /faq >}}

{{< faq question="Can I use EDN with other languages?" >}} Yes, EDN libraries exist for Python (pyedn), JavaScript, Ruby, and Java. But JSON remains more portable across languages. {{< /faq >}}

{{< faq question="What is Transit?" >}} Transit is a data transfer format built on top of EDN and JSON that adds extensible type handling with better performance and smaller payloads than raw EDN. {{< /faq >}}

{{< faq question="Can EDN represent cyclic data?" >}} No, EDN cannot represent cyclic data structures. Use records or custom serialization for graphs with cycles. {{< /faq >}}

{{< faq question="How do I handle large EDN files?" >}} Use clojure.java.io/reader with edn/read for streaming. For huge datasets, consider a database or specialized format. {{< /faq >}}

Mini Project

Create a configuration system for a web application using EDN:

;; Write configuration to EDN
(def config
  {:app {:name "MyApp" :version "1.0.0"}
   :database {:host "localhost" :port 5432}
   :features {:auth true :cache false}})

(spit "config.edn" (pr-str config))

;; Read configuration from EDN
(defn load-config [path]
  (edn/read-string (slurp path)))

What's Next

Now that you understand EDN, learn about reader macros that extend how Clojure reads code and data.

Topic Description Link
Clojure Reader Macros Customize Clojure's reader {{< ref "16-reader-macros" >}}
Clojure Transducers Efficient data processing {{< ref "17-transducers" >}}

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro