2015-10-20 17:26:37 +03:00
|
|
|
---
|
|
|
|
language: edn
|
|
|
|
filename: learnedn.edn
|
|
|
|
contributors:
|
|
|
|
- ["Jason Yeo", "https://github.com/jsyeo"]
|
2017-09-08 02:34:29 +03:00
|
|
|
- ["Jonathan D Johnston", "https://github.com/jdjohnston"]
|
2015-10-20 17:26:37 +03:00
|
|
|
---
|
|
|
|
|
2015-10-31 22:27:44 +03:00
|
|
|
Extensible Data Notation (EDN) is a format for serializing data.
|
2015-10-20 17:26:37 +03:00
|
|
|
|
2017-09-08 02:34:29 +03:00
|
|
|
EDN is a subset of the syntax used by Clojure. Reading data defined by EDN is
|
|
|
|
safer than that defined by the full Clojure syntax, especially from untrusted
|
|
|
|
sources. EDN is restricted to data, no code. It is similar in intent to JSON.
|
|
|
|
Though it is more commonly used in Clojure, there are implementations of EDN
|
|
|
|
for many other languages.
|
2015-10-20 17:26:37 +03:00
|
|
|
|
2015-10-31 22:27:44 +03:00
|
|
|
The main benefit of EDN over JSON and YAML is that it is extensible. We
|
2015-10-20 17:35:07 +03:00
|
|
|
will see how it is extended later on.
|
2015-10-20 17:26:37 +03:00
|
|
|
|
2016-02-13 10:04:31 +03:00
|
|
|
```clojure
|
2015-10-20 17:26:37 +03:00
|
|
|
; Comments start with a semicolon.
|
2015-10-31 03:33:13 +03:00
|
|
|
; Anything after the semicolon is ignored.
|
2015-10-20 17:26:37 +03:00
|
|
|
|
|
|
|
;;;;;;;;;;;;;;;;;;;
|
|
|
|
;;; Basic Types ;;;
|
|
|
|
;;;;;;;;;;;;;;;;;;;
|
|
|
|
|
2015-10-28 12:46:57 +03:00
|
|
|
nil ; also known in other languages as null
|
2015-10-20 17:26:37 +03:00
|
|
|
|
|
|
|
; Booleans
|
|
|
|
true
|
|
|
|
false
|
|
|
|
|
|
|
|
; Strings are enclosed in double quotes
|
|
|
|
"hungarian breakfast"
|
|
|
|
"farmer's cheesy omelette"
|
|
|
|
|
2017-08-23 11:14:39 +03:00
|
|
|
; Characters are preceded by backslashes
|
2015-10-20 17:26:37 +03:00
|
|
|
\g \r \a \c \e
|
|
|
|
|
2015-10-28 12:51:18 +03:00
|
|
|
; Keywords start with a colon. They behave like enums. Kind of
|
2015-10-28 12:46:57 +03:00
|
|
|
; like symbols in Ruby.
|
2015-10-20 17:26:37 +03:00
|
|
|
:eggs
|
|
|
|
:cheese
|
|
|
|
:olives
|
|
|
|
|
2017-10-20 21:50:20 +03:00
|
|
|
; Symbols are used to represent identifiers.
|
2017-08-23 11:14:39 +03:00
|
|
|
; You can namespace symbols by using /. Whatever precedes / is
|
2017-10-20 21:50:20 +03:00
|
|
|
; the namespace of the symbol.
|
|
|
|
spoon
|
|
|
|
kitchen/spoon ; not the same as spoon
|
|
|
|
kitchen/fork
|
|
|
|
github/fork ; you can't eat with this
|
2015-10-20 17:26:37 +03:00
|
|
|
|
|
|
|
; Integers and floats
|
|
|
|
42
|
|
|
|
3.14159
|
|
|
|
|
2015-10-28 12:46:57 +03:00
|
|
|
; Lists are sequences of values
|
2015-10-20 17:26:37 +03:00
|
|
|
(:bun :beef-patty 9 "yum!")
|
|
|
|
|
|
|
|
; Vectors allow random access
|
|
|
|
[:gelato 1 2 -2]
|
|
|
|
|
2015-10-31 22:27:44 +03:00
|
|
|
; Maps are associative data structures that associate the key with its value
|
2015-10-20 17:26:37 +03:00
|
|
|
{:eggs 2
|
|
|
|
:lemon-juice 3.5
|
|
|
|
:butter 1}
|
|
|
|
|
|
|
|
; You're not restricted to using keywords as keys
|
|
|
|
{[1 2 3 4] "tell the people what she wore",
|
|
|
|
[5 6 7 8] "the more you see the more you hate"}
|
|
|
|
|
2015-10-31 22:27:44 +03:00
|
|
|
; You may use commas for readability. They are treated as whitespace.
|
2015-10-20 17:26:37 +03:00
|
|
|
|
|
|
|
; Sets are collections that contain unique elements.
|
|
|
|
#{:a :b 88 "huat"}
|
|
|
|
|
2015-10-20 17:35:07 +03:00
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
;;; Tagged Elements ;;;
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;
|
2015-10-20 17:26:37 +03:00
|
|
|
|
|
|
|
; EDN can be extended by tagging elements with # symbols.
|
|
|
|
|
|
|
|
#MyYelpClone/MenuItem {:name "eggs-benedict" :rating 10}
|
|
|
|
|
2017-10-22 03:33:14 +03:00
|
|
|
; Let me explain this with a Clojure example. Suppose I want to transform that
|
2015-10-31 22:27:44 +03:00
|
|
|
; piece of EDN into a MenuItem record.
|
2015-10-20 17:26:37 +03:00
|
|
|
|
|
|
|
(defrecord MenuItem [name rating])
|
|
|
|
|
2017-10-22 03:33:14 +03:00
|
|
|
; defrecord defined, among other things, map->MenuItem which will take a map
|
|
|
|
; of field names (as keywords) to values and generate a user.MenuItem record
|
2015-10-20 17:26:37 +03:00
|
|
|
|
2017-10-22 03:33:14 +03:00
|
|
|
; To transform EDN to Clojure values, I will need to use the built-in EDN
|
|
|
|
; reader, clojure.edn/read-string
|
|
|
|
|
|
|
|
(clojure.edn/read-string "{:eggs 2 :butter 1 :flour 5}")
|
2015-10-20 17:26:37 +03:00
|
|
|
; -> {:eggs 2 :butter 1 :flour 5}
|
|
|
|
|
2017-10-22 03:33:14 +03:00
|
|
|
; To transform tagged elements, pass to clojure.edn/read-string an option map
|
|
|
|
; with a :readers map that maps tag symbols to data-reader functions, like so
|
2015-10-20 17:26:37 +03:00
|
|
|
|
2017-10-22 03:33:14 +03:00
|
|
|
(clojure.edn/read-string
|
|
|
|
{:readers {'MyYelpClone/MenuItem map->MenuItem}}
|
|
|
|
"#MyYelpClone/MenuItem {:name \"eggs-benedict\" :rating 10}")
|
2015-10-20 17:26:37 +03:00
|
|
|
; -> #user.MenuItem{:name "eggs-benedict", :rating 10}
|
|
|
|
```
|
|
|
|
|
|
|
|
# References
|
|
|
|
|
|
|
|
- [EDN spec](https://github.com/edn-format/edn)
|
|
|
|
- [Implementations](https://github.com/edn-format/edn/wiki/Implementations)
|
|
|
|
- [Tagged Elements](http://www.compoundtheory.com/clojure-edn-walkthrough/)
|